@sjawhar/opencode-legion-envoy 1.45.0 → 1.45.2
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
CHANGED
|
@@ -13848,7 +13848,6 @@ function componentsArgument(z) {
|
|
|
13848
13848
|
}
|
|
13849
13849
|
var SPEC_SECTIONS = [
|
|
13850
13850
|
"Summary",
|
|
13851
|
-
"Decisions needed",
|
|
13852
13851
|
"New since we talked",
|
|
13853
13852
|
"Acceptance",
|
|
13854
13853
|
"Requirements",
|
package/package.json
CHANGED
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -75,13 +75,11 @@ route"}`; when you see that, you typed the path wrong — read the index rather
|
|
|
75
75
|
|
|
76
76
|
## Writing a spec
|
|
77
77
|
|
|
78
|
-
A spec has two readers: the human who decides reads the top; the implementer who builds reads the
|
|
79
|
-
rest. Use these headings in this order.
|
|
78
|
+
A spec has two readers: the human who decides reads the **Summary** and **New since we talked** at the top, then each decision through its [`:::ask` block](#decision-blocks) where it arises; the implementer who builds reads the rest. Use these headings in this order.
|
|
80
79
|
|
|
81
80
|
| Section | Required content | Form |
|
|
82
81
|
| --- | --- | --- |
|
|
83
82
|
| **Summary** | The problem, what changes for whom, and how we will know it worked — in plain words. | Three sentences at most. |
|
|
84
|
-
| **Decisions needed** | Only decisions that need human authority, taste, or risk appetite: each one plain question, two or three options with what each costs, and your recommendation with its reason — written as an `ask` block directly under those options, so it is answered in context (see [Design changes are brainstormed here](#design-changes-are-brainstormed-here)). An answered item moves into Requirements with its provenance. | One `ask` block per decision; empty is fine. |
|
|
85
83
|
| **New since we talked** | Every design point the human did not settle in conversation, marked `inferred:` with the reasoning. Empty is fine. | One plain sentence per point. |
|
|
86
84
|
| **Acceptance** | Each outcome names what a user will observe and the check that proves it (browser scenario, API call, or command). An outcome without a check is not acceptance. | Numbered lines. |
|
|
87
85
|
| **Requirements** | What must hold, and where each came from: a quoted human sentence, or `inferred:` plus the reasoning. Readers treat inferred requirements as hypotheses. | `requirement \| where it comes from` table, or prose if the reader follows it more easily. |
|
|
@@ -94,13 +92,45 @@ rest. Use these headings in this order.
|
|
|
94
92
|
|
|
95
93
|
- The spec is the issue's one primary document. Extend it in place — a new version that keeps the
|
|
96
94
|
human's own text — never a second "spec" artifact beside it.
|
|
97
|
-
- No hedging ("might", "could consider"). No TBD, TODO, or placeholders: an open item is either
|
|
98
|
-
|
|
95
|
+
- No hedging ("might", "could consider"). No TBD, TODO, or placeholders: an open item is either
|
|
96
|
+
an ask block or a question for the platform PO whose ruling becomes a Requirement (see
|
|
99
97
|
[Before you ask](#before-you-ask) under Asking).
|
|
100
98
|
- Keep each section to one screen; work that exceeds one screen per section is two specs.
|
|
101
99
|
- Update the spec as decisions land: the spec is the record, comments are the discussion.
|
|
102
100
|
- Before sending it: no sections conflict, every requirement has exactly one reading, and the
|
|
103
|
-
Summary and
|
|
101
|
+
Summary and every ask block pass the phone test above.
|
|
102
|
+
|
|
103
|
+
## Decision blocks
|
|
104
|
+
|
|
105
|
+
A decision a human must make is an `:::ask` block where the decision arises in the spec: inside
|
|
106
|
+
the section whose content it is about, never gathered into a list at the top or bottom. Sami,
|
|
107
|
+
LEGION-204 comment, 2026-09-20 14:47Z, verbatim: "Adding a bunch of decision blocks at the top is
|
|
108
|
+
terrible!! Decisions should be in context in the spec".
|
|
109
|
+
|
|
110
|
+
The block is what reaches the human's Inbox. A question phrased as prose in the spec reaches
|
|
111
|
+
nobody. A spec with no ask blocks is fine only when the issue genuinely needs no human decision.
|
|
112
|
+
When `dispatch_issue` or `dispatch_artifact` answers `No decision blocks in this spec …`, read it
|
|
113
|
+
as a question, not an error: either no decision is needed and you say nothing, or you forgot to
|
|
114
|
+
make the decision a block and must fix the spec.
|
|
115
|
+
|
|
116
|
+
**Wrong:** a **Decisions needed** list at the top of the spec with three bullets.
|
|
117
|
+
**Right:** put each decision in the design section it belongs to as an `:::ask{#slug}` block, with
|
|
118
|
+
2–4 options, a recommendation, and surrounding prose that explains the trade-off.
|
|
119
|
+
|
|
120
|
+
A spec that already has the pile is repaired with `move`, not rewritten: `dispatch_doc_edit` with
|
|
121
|
+
`{ op: "move", block: "<block-uuid>", after: "<the sentence that states the options>" }` relocates
|
|
122
|
+
the block and keeps its ask, its answer and its followers; the context paragraphs that were lifted
|
|
123
|
+
out of Design move the same way, and the emptied section is deleted (the same repair, made on
|
|
124
|
+
AGENTC-397 after Sami's 2026-09-20 request: "move the decisions items to be in context of their
|
|
125
|
+
discussion in the spec, not just all piled up at the start with no context"). An ask block has two
|
|
126
|
+
ids: the block id, shown as `:::ask{#<uuid> …}` in the rendered document and taken bare by
|
|
127
|
+
`move`/`delete` in `block` (the `block:<uuid>` form is only for `before`/`after` anchors), and the
|
|
128
|
+
ask id, which `dispatch_open_asks`, the dashboard's `?ask=` link, `dispatch_read` and
|
|
129
|
+
`dispatch_comment({ reply_to_ask })` use. They differ; `dispatch://KEY/ask/<block-id>` answers
|
|
130
|
+
`not found`.
|
|
131
|
+
|
|
132
|
+
See [Typed blocks](#typed-blocks) for the syntax and [Before you ask](#before-you-ask) under
|
|
133
|
+
[Asking](#asking) to decide whether the question is a real decision at all.
|
|
104
134
|
|
|
105
135
|
## Your owner
|
|
106
136
|
|
|
@@ -152,6 +182,9 @@ renders its state and checks from that link. The call is authenticated with the
|
|
|
152
182
|
other `dispatch_*` tool: a Legion pane reads it from the `DISPATCH_TOKEN_FILE` path the daemon sets on
|
|
153
183
|
the pane; an OMP session outside Legion reads `dispatch.token` from `~/.config/opencode/envoy.json`.
|
|
154
184
|
|
|
185
|
+
A write to an issue still in `triage` answers once with `… is still in triage …`; move the status
|
|
186
|
+
when work has started.
|
|
187
|
+
|
|
155
188
|
## Search first
|
|
156
189
|
|
|
157
190
|
Before you create an issue or start a design document, search:
|
|
@@ -191,9 +224,10 @@ of having this discussion" (on a report-table shape), and "What's a fenced PutOb
|
|
|
191
224
|
eval_id? What's an R4 model header? What exactly is the question or uncertainty here?" (on a
|
|
192
225
|
production import). Every `dispatch_ask` passes three gates first:
|
|
193
226
|
|
|
194
|
-
1. **Does it need his authority, taste, or risk appetite?**
|
|
195
|
-
|
|
196
|
-
internals, and contracts between lanes do not: they go to
|
|
227
|
+
1. **Does it need his authority, taste, or risk appetite?** This is the bar for a decision
|
|
228
|
+
written as an `:::ask` block in context ([Decision blocks](#decision-blocks)). Schema shapes,
|
|
229
|
+
table layouts, field names, migration internals, and contracts between lanes do not: they go to
|
|
230
|
+
the platform PO over Envoy, who rules.
|
|
197
231
|
2. **Is there genuine uncertainty?** If not, it is a plan you execute. The one legitimate ask
|
|
198
232
|
without uncertainty is permission for an action only a human can authorise — a production
|
|
199
233
|
write, an external send, a console action — and then the question is that action in one
|
|
@@ -323,6 +357,11 @@ At least one field besides `ask` is required. Use this only while the same decis
|
|
|
323
357
|
log and invalidates any answer draft against the prior `edited_at` revision, so the human sees the new wording and explicitly reconfirms.
|
|
324
358
|
An answered or resolved ask cannot be edited. If the decision is moot or superseded, retract the old ask and open a new one.
|
|
325
359
|
|
|
360
|
+
An ask that lives as an `ask` block in a document takes its question and options from the document, so edit those with
|
|
361
|
+
`dispatch_doc_edit` (`replace` on the block's text, or `delete`/`insert` on its option items), never with `dispatch_edit_ask`: the
|
|
362
|
+
next document save reasserts the block's text over whatever `dispatch_edit_ask` wrote, and that reversal is logged as an edit by
|
|
363
|
+
the document's saver. `dispatch_edit_ask` is for asks opened with `dispatch_ask` that have no block.
|
|
364
|
+
|
|
326
365
|
An ask stays open until a human answers, unless its question no longer needs that answer. Retract a moot or superseded question, or
|
|
327
366
|
self-resolve one after finding the answer:
|
|
328
367
|
```ts
|
|
@@ -353,6 +392,26 @@ yet — "dispatched two auditors, back with results", "checking the release bran
|
|
|
353
392
|
turn to you. The result names the state (`ask now waiting on agent` / `human`), the delivered `comment.created` carries it as
|
|
354
393
|
`ask_waiting_on`, and every ask read carries it as `waiting_on`.
|
|
355
394
|
|
|
395
|
+
## Close what you opened
|
|
396
|
+
|
|
397
|
+
An ask you opened is yours until it is answered or you resolve it. When the answer arrives some
|
|
398
|
+
other way — Sami said it live, a later comment settled it, or the question became moot because the
|
|
399
|
+
design moved — resolve it yourself with `dispatch_resolve_ask` in the same turn you learn that.
|
|
400
|
+
Never leave it for the human to clear.
|
|
401
|
+
|
|
402
|
+
Sami, AGENTC-27 `rules-derivation-2026-09-17.md` row R04, verbatim: "I think this was answered
|
|
403
|
+
live. If not, please reask." The same pattern left him closing asks as `Dismissed`, `Settled`, and
|
|
404
|
+
`Resolved I think`: noise the human had to clear.
|
|
405
|
+
|
|
406
|
+
Every later write on the issue answers `You still have an open ask on …` and names it. Treat that
|
|
407
|
+
as the checklist: if it is still needed, leave it; if it was answered elsewhere, resolve it with
|
|
408
|
+
the resolving fact as the reason. Before posting a new ask, inspect your open ones. If the new ask
|
|
409
|
+
supersedes one, retract the old one with `dispatch_resolve_ask` and kind `retracted` in the same
|
|
410
|
+
turn.
|
|
411
|
+
|
|
412
|
+
See [Following](#following) for why you receive what happens to asks you open and
|
|
413
|
+
[What comes back](#what-comes-back) for finding them again with `dispatch_open_asks`.
|
|
414
|
+
|
|
356
415
|
## Approval of a spec
|
|
357
416
|
|
|
358
417
|
Approval is a property of a document, not a question you phrase: a human approves a specific version, the way a pull-request
|
|
@@ -592,6 +651,10 @@ high-signal, structured conversation"). The structure IS the product:
|
|
|
592
651
|
- **Never split one deliverable across a message + an ask that points at it.** Ask the question
|
|
593
652
|
with the document reference in the question text; the reader lands on the content in one click.
|
|
594
653
|
|
|
654
|
+
The tool result answers your third consecutive message on an issue with no human reply with
|
|
655
|
+
`You've sent N messages …`. That is the ledger pattern being named; stop and either wait or ask
|
|
656
|
+
once.
|
|
657
|
+
|
|
595
658
|
## Messages
|
|
596
659
|
|
|
597
660
|
Dispatch is a high-signal record for humans, not a log of what you are doing. A message is a reply to a human's message, or a
|
|
@@ -86,11 +86,11 @@ handoffs; do not narrate them into the spec or a `dispatch_message`. A blocker o
|
|
|
86
86
|
clear is a `dispatch_ask`.
|
|
87
87
|
|
|
88
88
|
The issue's primary document **is** the root specification. Extend it in place — a new version
|
|
89
|
-
that keeps the human's own text and adds Summary,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
that keeps the human's own text and adds Summary, New since we talked, the adoption/decomposition
|
|
90
|
+
and waves, acceptance criteria, and the integration test — never a second "spec" artifact beside
|
|
91
|
+
it (`dispatch_artifact` with the primary document's name replaces the human's document; do not do
|
|
92
|
+
that). Both readers described in [Writing for the human](../dispatch/SKILL.md#writing-for-the-human)
|
|
93
|
+
must be able to follow it.
|
|
94
94
|
The design gate runs only when the "Design gate policy" line at the end of your system prompt
|
|
95
95
|
says `gates.design: root-issues`. When it says `gates.design: off`, write the spec and continue
|
|
96
96
|
to section 2 with no approval step at all: do not request approval, do not register a gate, and
|