@sjawhar/opencode-legion-envoy 3.11.2 → 3.11.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/dist/src/server.js +2066 -7899
- package/package.json +2 -2
- package/skills/dispatch/SKILL.md +32 -2
- package/skills/legion-worker/SKILL.md +23 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjawhar/opencode-legion-envoy",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/server.js",
|
|
6
6
|
"exports": {
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"@types/bun": "latest",
|
|
47
47
|
"solid-js": "^1.9.0",
|
|
48
48
|
"typescript": "^5.3.0",
|
|
49
|
-
"zod": "
|
|
49
|
+
"zod": "4.3.6"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -154,7 +154,7 @@ exactly one owner to every owner-scoped tool: `issue` for an issue, or `project`
|
|
|
154
154
|
that GitHub issue or pull request. Only `dispatch_issue` with `external` creates a native issue; if no issue is linked, call
|
|
155
155
|
`dispatch_issue({ external: "owner/repo#n", project: "<project>", title: "<title>" })` before addressing it.
|
|
156
156
|
|
|
157
|
-
Issue reads include `rank`, the server-owned ordering key used by project boards; reorder through `PATCH /api/v1/issues/{key}` with
|
|
157
|
+
Issue reads include `rank`, the server-owned ordering key used by project boards; reorder through `PATCH /api/v1/issues/{key}` with `{"rank": {"before": "<key>", "after": "<key>"}}`, either neighbor optional and both in the issue's project. A bearer caller also names its own session in that body, `"actor": {"kind": "session", "id": "<your session id>"}`, or the server refuses with `ACTOR_KIND`. They also include nullable coarse priority (`P0` highest through `P3` lowest) and `assignee`: the lowercase GitHub login of the human who answers the issue's asks, or `null` when nobody holds it. `dispatch_read` of an issue prints it as `Assignee: <login>` or `Assignee: unassigned`.
|
|
158
158
|
|
|
159
159
|
### Who answers an ask
|
|
160
160
|
|
|
@@ -172,6 +172,36 @@ dispatch_issue({ project, title, parent?, external?, spec?, force?, labels?: str
|
|
|
172
172
|
`details` `{ issue }`; creating an issue does not subscribe you to it (see [Following](#following)). Use `dispatch_issue` only to create an issue; never use it to park a question. When `spec` is supplied,
|
|
173
173
|
follow [Writing a spec](#writing-a-spec).
|
|
174
174
|
|
|
175
|
+
## Choosing what to work on
|
|
176
|
+
|
|
177
|
+
When you finish an issue, or are told to work on the next thing, take the top ready issue of the
|
|
178
|
+
whole backlog, across every project: status `todo`, highest priority first, then board rank. There
|
|
179
|
+
are no areas: a standing role, a product owner and a lane each take the top issue like everyone
|
|
180
|
+
else (Sami, 2026-09-27, dispatch://AGENTC-34/ask/01ed2956-73cc-48d2-8ed4-7a86c6d439b1). `todo`
|
|
181
|
+
means ready: specced, unblocked, and waiting on neither a deploy nor a decision. An issue that
|
|
182
|
+
waits on one belongs in `backlog`, with what it waits on said on the issue.
|
|
183
|
+
|
|
184
|
+
Hold at most three issues in flight (`in_progress`, `testing`, `needs_review` or `retro`), of any
|
|
185
|
+
kind (Sami, 2026-09-27, answering dispatch://AGENTC-34/ask/1aeb8f2e-0950-4eaa-aaac-24286c9dd3ca;
|
|
186
|
+
the question proposed two, and his answer set three). The limit is per agent and has nothing to do
|
|
187
|
+
with the week's priorities (Sami, 2026-09-28, reply a7647eb0 on
|
|
188
|
+
dispatch://AGENTC-393/ask/b773d9f6): the priorities decide only what you pull next. Past three:
|
|
189
|
+
push any unfinished work, say where in one comment on the issue, move it to `backlog` and clear
|
|
190
|
+
its route. Each issue counts on its own; a child does not ride under its parent's slot.
|
|
191
|
+
In-flight issues with no owner at all go
|
|
192
|
+
back to `backlog` as well: no claim or route held by a live session, no Dispatch activity in the
|
|
193
|
+
last day, and no pull request moving on GitHub (an owner working there leaves no Dispatch trace).
|
|
194
|
+
The order keeper sweeps those. Never write the status of an issue that carries the `legion`
|
|
195
|
+
label, or of any issue under one: the Legion daemon writes those statuses, and moving one of its
|
|
196
|
+
admitted roots out of its flow parks the tree and stops its workers.
|
|
197
|
+
|
|
198
|
+
One agent keeps the backlog's order against those priorities, with Sami
|
|
199
|
+
(dispatch://AGENTC-34/ask/f6780f9e-8b96-49eb-9be7-7c7f2036d5cc). Setting an issue's priority
|
|
200
|
+
stays yours ([Priority is yours to set](#priority-is-yours-to-set)); reordering the board does not.
|
|
201
|
+
When the top of the backlog looks wrong, or a priority's next step is not yet a ready issue,
|
|
202
|
+
publish it to `notifications.role.backlog-order`, which the order keeper holds, instead of
|
|
203
|
+
reordering the board yourself.
|
|
204
|
+
|
|
175
205
|
## Claim the issue before you work it
|
|
176
206
|
|
|
177
207
|
Two sessions once spent a night implementing the same issue, because nothing on it said who was
|
|
@@ -300,7 +330,7 @@ This is not search: it matches no text. Use `dispatch_search` for a keyword or p
|
|
|
300
330
|
|
|
301
331
|
### The owner audit
|
|
302
332
|
|
|
303
|
-
As the owner of a surface, list
|
|
333
|
+
As the owner of a surface, list the project's P0 and P1 issues and staff or close each one nobody
|
|
304
334
|
has started:
|
|
305
335
|
```ts
|
|
306
336
|
dispatch_issues({ project, priority: [0, 1], limit: 250 })
|
|
@@ -285,9 +285,11 @@ later phase keeps it current rather than replacing it:
|
|
|
285
285
|
- Thread <id>: fixed in <commit-sha> — <one line>.
|
|
286
286
|
- Thread <id>: not a defect — <reason>.
|
|
287
287
|
`legion threads resolve --pr <n> --repo <owner>/<repo>` at <head-sha>:
|
|
288
|
-
resolved <thread URL>
|
|
288
|
+
resolved <thread URL> — its opener's acceptance
|
|
289
|
+
resolved <thread URL> — the Legion reviewer's acceptance of a bot's thread
|
|
289
290
|
left open <thread URL> — newest reply by <login> is not an acceptance
|
|
290
291
|
left open <thread URL> — newest reply by <login> is an unsubmitted draft in a pending review
|
|
292
|
+
left open <thread URL> — newest reply by <login> is not its opener's or the Legion reviewer's acceptance
|
|
291
293
|
|
|
292
294
|
**Thermo:** `ce-simplify-code` once at <head-sha>: <0 applied | applied → new head <sha>>; thermonuclear pair at the final head <sha>:
|
|
293
295
|
<verdict>. (omitted entirely on a docs-only PR — there is no code for either pass, so neither runs)
|
|
@@ -329,7 +331,8 @@ this proof.
|
|
|
329
331
|
|
|
330
332
|
- **Threads are dispositioned individually, never resolved in bulk.** Every open review
|
|
331
333
|
thread gets its own line naming the fixing commit or the reason it isn't a defect. The
|
|
332
|
-
reviewer answers each thread it opened
|
|
334
|
+
reviewer answers each thread it opened, and each thread a bot opened that is none of Legion's
|
|
335
|
+
role Apps, with exactly one of `Accepted: fixed in <commit> — <one line>`,
|
|
333
336
|
`Accepted: not a defect — <reason>`, or `Still open: <what remains>`; nothing else is an
|
|
334
337
|
acceptance, and nobody replies after an `Accepted:` (any later reply that is not itself an
|
|
335
338
|
`Accepted:` — the opener's own follow-up included — leaves the thread open, because resolution
|
|
@@ -341,9 +344,16 @@ this proof.
|
|
|
341
344
|
In a Legion pane, the **implementer** runs the command before every push that answers a review
|
|
342
345
|
(the corrective push and the final `.legion/` deletion push) and pastes its output into the
|
|
343
346
|
`Threads` section. The command resolves each unresolved thread whose newest submitted comment is
|
|
344
|
-
the opener's own `Accepted:` reply
|
|
345
|
-
|
|
346
|
-
|
|
347
|
+
the opener's own `Accepted:` reply. On a thread a bot account opened that is none of Legion's
|
|
348
|
+
role Apps (the daemon names them, keyed by App role), the Legion reviewer's `Accepted:` also
|
|
349
|
+
closes it. GitHub cannot tell a CI bot, which never accepts, from a person whose `gh` is routed
|
|
350
|
+
to an App, so the reviewer adjudicates such a finding, and it may accept one an App-routed person
|
|
351
|
+
raised. The subject of a finding never closes it: the implementer's `Fixed in <commit>: …` or
|
|
352
|
+
`Declined: …` answers a thread and closes none. A thread either Legion App opened, a reviewer's
|
|
353
|
+
finding included, still needs its opener's `Accepted:`. It makes one `resolveReviewThread` per
|
|
354
|
+
thread, prints `resolved <url> — <whose acceptance>` (its opener's, or the Legion reviewer's on a
|
|
355
|
+
bot's thread, so the ledger shows which) or `left open <url> — newest reply by <login> is …`
|
|
356
|
+
naming why, and exits 1 naming the thread's URL and GitHub's message when GitHub refuses one.
|
|
347
357
|
|
|
348
358
|
Without a grant, page through `reviewThreads`, skip `isResolved: true`, and compare the opener
|
|
349
359
|
with the newest comment. Query shape, inside `repository { pullRequest { … } }`:
|
|
@@ -353,15 +363,18 @@ this proof.
|
|
|
353
363
|
pageInfo { hasNextPage endCursor }
|
|
354
364
|
nodes {
|
|
355
365
|
id isResolved
|
|
356
|
-
opener: comments(first: 1) { nodes { author { login } } }
|
|
357
|
-
newest: comments(last: 1) { nodes { author { login } body state } }
|
|
366
|
+
opener: comments(first: 1) { nodes { author { __typename login } } }
|
|
367
|
+
newest: comments(last: 1) { nodes { author { __typename login } body state } }
|
|
358
368
|
}
|
|
359
369
|
}
|
|
360
370
|
```
|
|
361
371
|
|
|
362
|
-
Resolve only when the newest comment is submitted, its `author
|
|
363
|
-
and
|
|
364
|
-
|
|
372
|
+
Resolve only when the newest comment is submitted, its `author` is the opener's account (the same
|
|
373
|
+
`__typename` and `login`: a login alone is a string anyone may register), and its `body`, after
|
|
374
|
+
removing leading spaces, tabs, CR, and LF, begins `Accepted:`. Without a
|
|
375
|
+
grant nothing names Legion's own App logins, so this route closes a bot's thread only on its
|
|
376
|
+
opener's `Accepted:`: leave one the Legion reviewer accepted for the implementer's or merger's
|
|
377
|
+
run in a pane, or report it. For each thread to resolve:
|
|
365
378
|
|
|
366
379
|
```graphql
|
|
367
380
|
mutation($threadId: ID!) {
|