@sjawhar/opencode-legion-envoy 1.14.1 → 1.16.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/dist/src/server.js +8 -1
- package/package.json +1 -1
- package/skills/dispatch/SKILL.md +3 -3
- package/skills/legion-architect/SKILL.md +8 -1
- package/skills/legion-controller/SKILL.md +7 -0
- package/skills/legion-oracle/SKILL.md +6 -5
- package/skills/legion-retro/SKILL.md +8 -0
- package/skills/legion-worker/SKILL.md +33 -1
package/dist/src/server.js
CHANGED
|
@@ -13567,6 +13567,7 @@ var IssueEventPayloadSchema = object({
|
|
|
13567
13567
|
title: string2().optional(),
|
|
13568
13568
|
labels: array(string2()).optional(),
|
|
13569
13569
|
status: string2().optional(),
|
|
13570
|
+
priority: number2().int().min(0).max(3).nullable().optional(),
|
|
13570
13571
|
rank: string2().optional(),
|
|
13571
13572
|
route: string2().nullish()
|
|
13572
13573
|
});
|
|
@@ -13762,7 +13763,8 @@ var dispatchToolSpecs = [
|
|
|
13762
13763
|
external: z.string().describe("Optional external issue reference.").optional(),
|
|
13763
13764
|
force: z.boolean().describe("Create even though POSSIBLE_DUPLICATE listed similar issues; pass it only after reading them.").optional(),
|
|
13764
13765
|
spec: z.string().describe(`Optional initial primary-document markdown. ${SPEC_WRITING_GUIDANCE}`).optional(),
|
|
13765
|
-
labels: z.array(z.string({ min: 1, max: 40 }), { max: 20 }).describe("Optional initial labels, at most 20 labels of up to 40 characters.").optional()
|
|
13766
|
+
labels: z.array(z.string({ min: 1, max: 40 }), { max: 20 }).describe("Optional initial labels, at most 20 labels of up to 40 characters.").optional(),
|
|
13767
|
+
priority: z.number({ int: true, min: 0, max: 3 }).describe("Optional coarse priority: P0 is highest and P3 is lowest.").optional()
|
|
13766
13768
|
})
|
|
13767
13769
|
},
|
|
13768
13770
|
{
|
|
@@ -15208,10 +15210,13 @@ function issueSummary(issue, events, references) {
|
|
|
15208
15210
|
const asks = issue.open_asks;
|
|
15209
15211
|
const spec = issue.artifacts?.find((artifact) => artifact.primary);
|
|
15210
15212
|
const specApproval = spec === undefined ? undefined : approvalLine(spec);
|
|
15213
|
+
if (issue.priority === undefined)
|
|
15214
|
+
throw new Error("Dispatch issue is missing priority");
|
|
15211
15215
|
return [
|
|
15212
15216
|
`Title: ${issue.title}`,
|
|
15213
15217
|
`Key: ${issue.key}`,
|
|
15214
15218
|
`Status: ${issue.status}`,
|
|
15219
|
+
...issue.priority === null ? [] : [`Priority: P${issue.priority}`],
|
|
15215
15220
|
`Labels: ${issue.labels.length === 0 ? "none" : issue.labels.join(", ")}`,
|
|
15216
15221
|
`Route: ${issue.route ?? "none"}`,
|
|
15217
15222
|
...specApproval === undefined ? [] : [`Spec ${specApproval.replace(/^Approval/, "approval")}`],
|
|
@@ -15345,6 +15350,7 @@ async function executeDispatchTool(input) {
|
|
|
15345
15350
|
const external = optionalString(args, "external");
|
|
15346
15351
|
const force = optionalBoolean(args, "force");
|
|
15347
15352
|
const spec = optionalString(args, "spec");
|
|
15353
|
+
const priority = optionalNumber(args, "priority");
|
|
15348
15354
|
const labels = args.labels;
|
|
15349
15355
|
try {
|
|
15350
15356
|
const created = await client.issue({
|
|
@@ -15354,6 +15360,7 @@ async function executeDispatchTool(input) {
|
|
|
15354
15360
|
...external === undefined ? {} : { external },
|
|
15355
15361
|
...force === undefined ? {} : { force },
|
|
15356
15362
|
...spec === undefined ? {} : { spec },
|
|
15363
|
+
...priority === undefined ? {} : { priority },
|
|
15357
15364
|
...Array.isArray(labels) ? { labels } : {},
|
|
15358
15365
|
actor
|
|
15359
15366
|
});
|
package/package.json
CHANGED
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -78,13 +78,13 @@ exactly one owner to every owner-scoped tool: `issue` for an issue, or `project`
|
|
|
78
78
|
[References](#references) for the resulting ref shape). On first use, an external issue reference creates its native issue in the
|
|
79
79
|
project configured for that repository in Dispatch Settings, then falls back to `DISPATCH_DEFAULT_PROJECT`.
|
|
80
80
|
|
|
81
|
-
Issue reads include `rank`, the server-owned ordering key used by project boards; reorder through `PATCH /api/v1/issues/{key}` with neighboring issue keys
|
|
81
|
+
Issue reads include `rank`, the server-owned ordering key used by project boards; reorder through `PATCH /api/v1/issues/{key}` with neighboring issue keys. They also include nullable coarse priority (`P0` highest through `P3` lowest).
|
|
82
82
|
|
|
83
83
|
Architects create newly tracked child work with:
|
|
84
84
|
```ts
|
|
85
|
-
dispatch_issue({ project, title, parent?, external?, spec?, force?, labels?: string[] })
|
|
85
|
+
dispatch_issue({ project, title, parent?, external?, spec?, force?, labels?: string[], priority?: 0 | 1 | 2 | 3 })
|
|
86
86
|
```
|
|
87
|
-
`labels` are optional initial labels: Dispatch trims them, preserves their case, and removes case-insensitive duplicates. It returns
|
|
87
|
+
`labels` are optional initial labels: Dispatch trims them, preserves their case, and removes case-insensitive duplicates. Set `priority` on creation only when the human's intent makes the bucket clear; otherwise priority remains the human's decision. It returns
|
|
88
88
|
`details` `{ issue, topic }`. Use `dispatch_issue` only to create an issue; never use it to park a question. When `spec` is supplied,
|
|
89
89
|
follow [Writing a spec](#writing-a-spec).
|
|
90
90
|
|
|
@@ -34,6 +34,13 @@ separate coordinator to finish necessary work.
|
|
|
34
34
|
create and continue to own. Re-file a genuinely independent child through the
|
|
35
35
|
controller rather than treating it as an abandoned dependency.
|
|
36
36
|
|
|
37
|
+
## Deployment instructions
|
|
38
|
+
|
|
39
|
+
Deployment instructions, when present, are the operator's standing rules for this repository —
|
|
40
|
+
required checks, deploy/smoke commands, code-owner expectations, standing roles you may consult,
|
|
41
|
+
the merge credential. They override this skill's defaults where they conflict; they never
|
|
42
|
+
override a Sami ruling quoted here.
|
|
43
|
+
|
|
37
44
|
## 1. Decompose or adopt
|
|
38
45
|
|
|
39
46
|
Inspect the root issue, acceptance criteria, existing children, and current handoffs.
|
|
@@ -237,7 +244,7 @@ corresponding lifecycle procedure.
|
|
|
237
244
|
| `worker-started` | Payload `{type:"worker-started", issue, role}`. A previously queued role has been promoted and is now running. Treat it exactly as a normal spawn: resume tracking that role's live session. |
|
|
238
245
|
| `pr-ready` | Verify the live PR head, green status, and review state. Continue the review/retro/merger order only for that current head. |
|
|
239
246
|
| `pr-review` | Payload `{type:"pr-review", state, author, body}`. Delivered to whichever role is currently active for the issue, falling back to you when no worker phase is active. Follows the same verdict rule as a reviewer's `phase-complete`: `state: "changes_requested"` sends the implementer back in with the review findings, then tester, then reviewer — never the reviewer again and never retro; `state: "approved"` proceeds toward retro (step 5) once the step 6 integration/merge-gate conditions are met. |
|
|
240
|
-
| `pr-blocked` | Read the failed CI evidence and recovery attempts. Assign a focused implementer or corrective child, then return it through testing and review; do not treat the blocked PR as final. |
|
|
247
|
+
| `pr-blocked` | Payload `{type:"pr-blocked", pr, attempts}`. `attempts` counts heads pushed onto a red verdict that changed something outside `.legion/` — handoff-only pushes (`.legion/` paths only) never count; a push the daemon cannot classify (a listener without `changed_paths`, a list capped at 100, a push listing no commits) does. Published once per exhausted count, not on every later red verdict for that count. Read the failed CI evidence and recovery attempts. Assign a focused implementer or corrective child, then return it through testing and review; do not treat the blocked PR as final. |
|
|
241
248
|
| `pr-merged` | Payload `{type:"pr-merged", pr, mergeCommitSha}`. The merge queue landed the PR. This is your cue for step 7: post the sign-off comment naming that merge commit and set the issue `done`. Nothing else follows a merge. |
|
|
242
249
|
| `pr-closed-unmerged` | Decide from current scope whether to reopen the work, send a fresh implementer, or cancel it with a reason. Delegate the repository action to the responsible phase worker and keep ownership. |
|
|
243
250
|
| `issue-comment` | Interpret the comment in the issue's design context. Answer it, adjust the plan, or relay it via `envoy_publish` to the responsible worker's role token; scope and product decisions remain with you. |
|
|
@@ -33,6 +33,13 @@ listener restart.
|
|
|
33
33
|
This handshake lets the daemon redeliver held controller work. It does not turn the controller
|
|
34
34
|
into a state holder: daemon state and the Dispatch project remain authoritative.
|
|
35
35
|
|
|
36
|
+
## Deployment instructions
|
|
37
|
+
|
|
38
|
+
Deployment instructions, when present, are the operator's standing rules for this repository —
|
|
39
|
+
required checks, deploy/smoke commands, code-owner expectations, standing roles you may consult,
|
|
40
|
+
the merge credential. They override this skill's defaults where they conflict; they never
|
|
41
|
+
override a Sami ruling quoted here.
|
|
42
|
+
|
|
36
43
|
## Turn discipline
|
|
37
44
|
|
|
38
45
|
- **Direct user message always first.** If this turn includes a direct user message, answer
|
|
@@ -36,11 +36,12 @@ digraph oracle_decision {
|
|
|
36
36
|
|
|
37
37
|
## Research Strategy
|
|
38
38
|
|
|
39
|
-
If the deployment instructions name a librarian role,
|
|
40
|
-
`notifications.role.<name>`
|
|
41
|
-
OK), and 3-4 if needed, with tools a Legion
|
|
42
|
-
|
|
43
|
-
read-only analysis when the answer needs
|
|
39
|
+
If the deployment instructions name a librarian (or oracle) role, publish your question to
|
|
40
|
+
`notifications.role.<name>` with `expects_reply: required` and wait for the reply before
|
|
41
|
+
researching yourself. Then run steps 1-2 (parallel OK), and 3-4 if needed, with tools a Legion
|
|
42
|
+
pane actually has: `read`, `grep`, `web_search`, and `task(agent="scout")` (fast read-only
|
|
43
|
+
codebase search) or `task(agent="oracle")` (deeper read-only analysis when the answer needs
|
|
44
|
+
judgment across many files). Do not name any other agent.
|
|
44
45
|
|
|
45
46
|
| Step | Tool | Query |
|
|
46
47
|
|------|------|-------|
|
|
@@ -21,6 +21,10 @@ retrospective's durable output.
|
|
|
21
21
|
Retro writes **no `.legion` file**, so it never re-dirties the cleaned handoff tree.
|
|
22
22
|
4. The merger verifies the approved head, publishes `READY`, and pushes nothing; the merge queue
|
|
23
23
|
merges under the repository's own rules.
|
|
24
|
+
5. After the merge lands, the implementer — not the reviewer, the merger, or the queue — verifies
|
|
25
|
+
the change in production and records it on the PR and the issue (Sami, 2026-09-13, verbatim:
|
|
26
|
+
"the agent that developed it should be responsible for testing in production"). The
|
|
27
|
+
architect's sign-off waits for that record.
|
|
24
28
|
|
|
25
29
|
Do not start retro before step 2, skip it because the change seems mechanical, or publish `READY`
|
|
26
30
|
before step 3. The design gate is not a substitute for review and retro.
|
|
@@ -28,6 +32,10 @@ before step 3. The design gate is not a substitute for review and retro.
|
|
|
28
32
|
## Two perspectives
|
|
29
33
|
|
|
30
34
|
1. Re-read the issue, its acceptance criteria, the PR, test evidence, and review evidence.
|
|
35
|
+
Confirm the PR's `E2E` line links a pre-merge proof on a production-like surface (a devN
|
|
36
|
+
stack, staging, or a local stack with real migrations). If it links only a unit suite or
|
|
37
|
+
nothing, the retro's first durable learning is that gap, and the issue goes back to the
|
|
38
|
+
tester before `READY`.
|
|
31
39
|
Do not rebase or create a new branch; work on the existing issue branch.
|
|
32
40
|
2. Spawn one fresh-eyes subagent. Give it the issue and PR, ask it to inspect the diff and
|
|
33
41
|
return concrete reusable learnings, and require it to return analysis rather than edit files.
|
|
@@ -55,6 +55,13 @@ round, a question) can deliver a new prompt to this same session. Treat it as a
|
|
|
55
55
|
continuation — re-read the current issue and your own prior handoff, since time has
|
|
56
56
|
passed — never as a fresh identity.
|
|
57
57
|
|
|
58
|
+
## Deployment instructions
|
|
59
|
+
|
|
60
|
+
Deployment instructions, when present, are the operator's standing rules for this repository —
|
|
61
|
+
required checks, deploy/smoke commands, code-owner expectations, standing roles you may consult,
|
|
62
|
+
the merge credential. They override this skill's defaults where they conflict; they never
|
|
63
|
+
override a Sami ruling quoted here.
|
|
64
|
+
|
|
58
65
|
## Asking another role
|
|
59
66
|
|
|
60
67
|
Reach any live role on this issue the same way you reach the architect: `envoy_publish` to
|
|
@@ -242,7 +249,23 @@ Negative control: <deliberately broken input> → <refusal or failure observed>.
|
|
|
242
249
|
- The tester fills in the `E2E` section: the real surface a user reaches the criterion
|
|
243
250
|
through, the exact command or run id, what was observed, the head SHA, and one negative
|
|
244
251
|
control — a deliberately broken input and the refusal or failure it produced. A unit or
|
|
245
|
-
integration test is a regression lock, never proof of a criterion.
|
|
252
|
+
integration test is a regression lock, never proof of a criterion. The surface is
|
|
253
|
+
**production-like** — a devN stack, staging, or a local stack with real migrations, one that
|
|
254
|
+
has the resource the change touches — and the `E2E` line carries a **link** to that run,
|
|
255
|
+
screenshot, or e2e; the merge queue does not approve a user-facing change without it, and a
|
|
256
|
+
green unit suite is not it. Sami, 2026-09-13, verbatim: "They need to test everything in a
|
|
257
|
+
production-like environment before merging, and it is the agent that develops the feature
|
|
258
|
+
that is responsible for doing that. If there's anything blocking that, we need to fix it: if
|
|
259
|
+
it's infrastructure, we need to fix it; if it's tooling, we need to develop it; if it's
|
|
260
|
+
skills, we need to fix the skills ... it should not require deploying to production to
|
|
261
|
+
realize your feature doesn't work." A code path whose first execution is after merge — a
|
|
262
|
+
deploy workflow's inline step, a post-merge helper, a production-only resource — is untested
|
|
263
|
+
until the implementer has executed it against a devN stack; if no surface can reach it, the
|
|
264
|
+
tester names that missing surface as the blocker instead of passing the phase. Evidence for
|
|
265
|
+
the rule: in the week of 2026-09-08 three surfaces merged green and were wrong on inspection
|
|
266
|
+
(the Astrolabe IPI stack, Dispatch on ECS, the candidate flow), and on 2026-09-12 six deploy
|
|
267
|
+
slots died on code first executed after merge, including a production-only ECS bootstrap the
|
|
268
|
+
whole staging gate never ran. Environment or
|
|
246
269
|
secret-scrub evidence (e.g. "`LEGION_*`/`DISPATCH_*`/`ENVOY_*` unset") is recorded once, in
|
|
247
270
|
`.legion/test.json`, and only when the issue's acceptance criteria call for it — never
|
|
248
271
|
re-pasted into the PR body each round.
|
|
@@ -266,6 +289,15 @@ Negative control: <deliberately broken input> → <refusal or failure observed>.
|
|
|
266
289
|
`READY #<n> at <sha>` plus the PR body's gate facts to the merge queue's role
|
|
267
290
|
(`notifications.role.pr-queue`) with `envoy_publish`. The merger never merges; the queue
|
|
268
291
|
merges under its own authority.
|
|
292
|
+
- **After the queue merges, the implementer verifies in production.** Sami, 2026-09-13,
|
|
293
|
+
verbatim: "the agent that developed it should be responsible for testing in production."
|
|
294
|
+
The architect sends the implementer back once the merge lands; the implementer watches the
|
|
295
|
+
deploy slot that carries the merge to `production-apply` (or the equivalent publish step),
|
|
296
|
+
drives the changed path in production through the user's own access path, and records the
|
|
297
|
+
observation on the PR and the issue before the architect signs off. A staging pass is not
|
|
298
|
+
this: on 2026-09-12 a slot's entire staging gate passed at 00:02Z and its production-apply
|
|
299
|
+
failed at 00:12Z on a resource staging never runs. If the slot fails on the change, the
|
|
300
|
+
implementer owns the fix and the next slot.
|
|
269
301
|
|
|
270
302
|
## Completion gate: handoff write, verification, and persistence
|
|
271
303
|
|