@sjawhar/opencode-legion-envoy 6.4.2 → 6.5.1
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/README.md +13 -36
- package/bin/dispatch +6 -0
- package/dist/dispatch.js +18648 -0
- package/dist/src/server.js +238 -3570
- package/package.json +4 -3
- package/skills/dispatch/SKILL.md +85 -97
- package/skills/dispatch/references/api.md +4 -4
- package/skills/dispatch/references/asks.md +34 -54
- package/skills/dispatch/references/document-edits.md +24 -21
- package/skills/dispatch/references/documents.md +75 -72
- package/skills/dispatch/references/examples.md +37 -67
- package/skills/dispatch/references/issues.md +48 -48
- package/skills/dispatch/references/messages.md +18 -25
- package/skills/dispatch/references/reading.md +10 -10
- package/skills/dispatch-brainstorming/SKILL.md +19 -15
- package/skills/dispatch-first/SKILL.md +7 -7
- package/skills/envoy/SKILL.md +3 -2
- package/skills/legion-architect/SKILL.md +47 -49
- package/skills/legion-controller/SKILL.md +38 -32
- package/skills/legion-retro/SKILL.md +7 -8
- package/skills/legion-worker/SKILL.md +20 -15
- package/skills/legion-worker/references/merge-gate.md +3 -3
- package/src/server.ts +54 -36
|
@@ -7,11 +7,8 @@ thread. Whether to ask at all, and how to write the question, is "Before you ask
|
|
|
7
7
|
|
|
8
8
|
## Who answers an ask
|
|
9
9
|
|
|
10
|
-
An ask goes to the issue's assignee: their Inbox opens on **Mine**, which lists asks on the issues they hold plus an Unassigned band; an ask on an unassigned issue waits in that band for someone to take it. Find out who Dispatch takes you for with
|
|
11
|
-
|
|
12
|
-
dispatch_whoami({})
|
|
13
|
-
```
|
|
14
|
-
It returns `details` `{ session, owner, service }`: `owner` is the lowercase email of the person whose personal token you run under, or `null` under the shared token or a verified service token, in which case `service` is that token's subject (`system:serviceaccount:<namespace>:<name>`, `null` otherwise) and every write you make is rendered `(as <namespace>/<name>)` — the namespace is kept because every namespace has a `default` service account, and a subject that is not a Kubernetes one is shown whole. An issue you create without `assignee` goes to your owner; with no owner it inherits its parent's assignee, or stays unassigned without a parent. If an issue you are asking on is unassigned and the answer matters, assign it to your owner (`PATCH /api/v1/issues/{key}` with `{"assignee": "<email>"}`; any authenticated caller may reassign, and an email nobody has signed in with is refused with `ASSIGNEE_NOT_ALLOWED`) or name in the question who should answer it. Never reassign an issue a human holds to get an answer faster: that is the human's call.
|
|
10
|
+
An ask goes to the issue's assignee: their Inbox opens on **Mine**, which lists asks on the issues they hold plus an Unassigned band; an ask on an unassigned issue waits in that band for someone to take it. Find out who Dispatch takes you for with `dispatch whoami`.
|
|
11
|
+
It prints whom the session acts for: the lowercase email of the person whose personal token you run under, or, under the shared token or a verified service token, that it has no owner — naming the service as `<namespace>/<name>` for a service token (`system:serviceaccount:<namespace>:<name>`), which is also how every write you make is rendered (`(as <namespace>/<name>)`) — the namespace is kept because every namespace has a `default` service account, and a subject that is not a Kubernetes one is shown whole. An issue you create without `--assignee` goes to your owner; with no owner it inherits its parent's assignee, or stays unassigned without a parent. If an issue you are asking on is unassigned and the answer matters, assign it to your owner (`PATCH /api/v1/issues/{key}` with `{"assignee": "<email>"}`; any authenticated caller may reassign, and an email nobody has signed in with is refused with `ASSIGNEE_NOT_ALLOWED`) or name in the question who should answer it. Never reassign an issue a human holds to get an answer faster: that is the human's call.
|
|
15
12
|
|
|
16
13
|
## Handing a human a to-do, editing, resolving, and replying
|
|
17
14
|
|
|
@@ -20,41 +17,28 @@ A to-do handed to a human still follows the question and options contract that `
|
|
|
20
17
|
answer. There is no fixed vocabulary and the server treats no label specially.
|
|
21
18
|
If an outcome needs a reason, say so in that option's description, and the human's free-text answer
|
|
22
19
|
carries it:
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
options: [
|
|
29
|
-
{ label: "Deploy the verified fix", description: "Restores the fix but can expose a deployment problem." },
|
|
30
|
-
{ label: "Hold the deploy", description: "Avoids a production change now but leaves production without the fix." },
|
|
31
|
-
],
|
|
32
|
-
})
|
|
20
|
+
```bash
|
|
21
|
+
dispatch ask --issue DSP-42 \
|
|
22
|
+
--question 'The verified fix remains unavailable in production because deployment is pending. Deploying changes production and could expose a deployment problem. How should we proceed? Recommendation: deploy the verified fix now because it restores the intended behavior.' \
|
|
23
|
+
--option 'Deploy the verified fix: Restores the fix but can expose a deployment problem.' \
|
|
24
|
+
--option 'Hold the deploy: Avoids a production change now but leaves production without the fix.'
|
|
33
25
|
```
|
|
34
26
|
|
|
35
|
-
Correct or refine an open ask in place instead of opening a second question
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ask,
|
|
39
|
-
question?,
|
|
40
|
-
options?: { label, description? }[],
|
|
41
|
-
multiple?,
|
|
42
|
-
urgency?,
|
|
43
|
-
})
|
|
44
|
-
```
|
|
45
|
-
At least one field besides `ask` is required. Use this only while the same decision remains open: it keeps the prior text in the event
|
|
27
|
+
Correct or refine an open ask in place instead of opening a second question, with
|
|
28
|
+
`dispatch edit-ask --ask <id>` and any of `--question`, `--option` (repeated), `--multiple` and `--urgency`.
|
|
29
|
+
At least one of them is required. Use this only while the same decision remains open: it keeps the prior text in the event
|
|
46
30
|
log and invalidates any answer draft against the prior `edited_at` revision, so the human sees the new wording and explicitly reconfirms.
|
|
47
31
|
An answered or resolved ask cannot be edited. If the decision is moot or superseded, retract the old ask and open a new one.
|
|
48
32
|
A human can change an answer they gave. The change arrives as another `ask.answered` frame whose
|
|
49
33
|
`previous_answer` names the answer it replaced, through the same route the first answer took, and
|
|
50
|
-
`
|
|
34
|
+
`dispatch read --ref dispatch://KEY/ask/<id>` lists every earlier answer. Act on the newest answer.
|
|
51
35
|
|
|
52
|
-
An ask that lives as an `ask` block in a document keeps its question and options in the block, and `
|
|
53
|
-
block along with the row, so the edit stands and the document reads the same. It changes only the fields you name: pass
|
|
54
|
-
alone and the question's own wording, formatting, links and comment anchors are untouched. Pass
|
|
36
|
+
An ask that lives as an `ask` block in a document keeps its question and options in the block, and `dispatch edit-ask` writes the
|
|
37
|
+
block along with the row, so the edit stands and the document reads the same. It changes only the fields you name: pass `--urgency`
|
|
38
|
+
alone and the question's own wording, formatting, links and comment anchors are untouched. Pass `--question` or `--option` and that part
|
|
55
39
|
is rewritten, so anchors inside the text you replaced move as they would for any document edit. Either way it is a document edit: it
|
|
56
40
|
writes a new version, which on a spec awaiting approval closes the design gate until the new version is approved. Editing the block
|
|
57
|
-
with `
|
|
41
|
+
with `dispatch doc-edit` works too and is the way to change anything else about it, including adding formatting to a question.
|
|
58
42
|
Re-sending a field unchanged rewrites nothing, so retrying the whole ask is safe.
|
|
59
43
|
Text the block cannot carry back unchanged is refused outright, naming the field and writing nothing - an option label containing
|
|
60
44
|
`": "`, the separator between a label and its description, is one example of text that cannot survive the round trip. Blank lines separate paragraphs;
|
|
@@ -62,51 +46,47 @@ a single newline is kept as a line break.
|
|
|
62
46
|
|
|
63
47
|
An ask stays open until a human answers, unless its question no longer needs that answer. Retract a moot or superseded question, or
|
|
64
48
|
self-resolve one after finding the answer:
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
ask,
|
|
68
|
-
kind: "retracted",
|
|
69
|
-
reason: "A newer ask supersedes this question.",
|
|
70
|
-
})
|
|
49
|
+
```bash
|
|
50
|
+
dispatch resolve-ask --ask <id> --kind retracted --reason 'A newer ask supersedes this question.'
|
|
71
51
|
```
|
|
72
52
|
Use `retracted` when the question is obsolete and `resolved` when you found the answer. Include the reason because the question remains
|
|
73
53
|
in its Conversation card and reply thread; a reason beginning `removed from the document in version` is refused, because that is how a
|
|
74
54
|
retraction the document's own settlement wrote is recognised. Resolving a block ask records it in the block too, so it stays resolved
|
|
75
|
-
however the document moves afterwards. `
|
|
76
|
-
whole-document `
|
|
77
|
-
resolved. A human may reply to an open or answered ask; so may you, e.g. after finding the answer — use `
|
|
78
|
-
`
|
|
79
|
-
A review comment you opened has its own closer, `
|
|
55
|
+
however the document moves afterwards. `dispatch doc-edit` refuses deleting the block of an open ask; a block removed another way, by a
|
|
56
|
+
whole-document `dispatch artifact` replace or by a person in the browser, closes its ask, and putting the block back reopens it. Resolution is not an answer: it never records a human decision, and an answered ask cannot be
|
|
57
|
+
resolved. A human may reply to an open or answered ask; so may you, e.g. after finding the answer — use `--reply-to-ask` on
|
|
58
|
+
`dispatch comment` (mutually exclusive with `--reply-to`).
|
|
59
|
+
A review comment you opened has its own closer, `dispatch resolve-comment` — see
|
|
80
60
|
[Comments and suggestions](skill://dispatch/references/documents.md).
|
|
81
61
|
|
|
82
62
|
A human answers or asks back from the same field; a question-shaped free-text answer is offered as a clarification first. A human
|
|
83
63
|
reply while your ask is still open (the delivered `comment.created` carries `ask_state: open`) is a request for clarification, not
|
|
84
64
|
an answer: the human did not understand the question or needs more before choosing. The ask now waits on you in their Inbox. Answer
|
|
85
|
-
in the same thread with `
|
|
65
|
+
in the same thread with `dispatch comment --reply-to-ask <id>`, or reword the question itself with `dispatch edit-ask` when the wording
|
|
86
66
|
was the problem; either puts the ask back in front of them. Do not open a second ask.
|
|
87
67
|
|
|
88
68
|
Every reply to an open ask says whose turn it is next, and the Inbox files the ask by that, not by who spoke last. Your plain reply
|
|
89
|
-
(
|
|
69
|
+
(`--turn` omitted, or `--turn human`) hands the turn to the human: the ask returns to their `Waiting on you`. When you are not done
|
|
90
70
|
yet — "dispatched two auditors, back with results", "checking the release branch, back shortly", any working-on-it note — reply with
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
turn to you. The
|
|
71
|
+
`--turn agent`: the note lands in the thread, the ask stays under `Waiting on agents`, and the human is not told to act. Use
|
|
72
|
+
`--turn agent` for every progress note and `--turn human` (the default) only when you need them. A human's reply always hands the
|
|
73
|
+
turn to you. The output names the state (`ask now waiting on agent` / `human`), the delivered `comment.created` carries it as
|
|
94
74
|
`ask_waiting_on`, and every ask read carries it as `waiting_on`.
|
|
95
75
|
|
|
96
76
|
## Following
|
|
97
77
|
|
|
98
78
|
An ask has followers: every session that wrote to it — the session that opened it and every session that replied with
|
|
99
|
-
`
|
|
79
|
+
`dispatch comment --reply-to-ask` — plus any session a human adds from the ask card. The ask's answer, edits, resolution, and
|
|
100
80
|
every reply on it reach each follower's own agent topic directly, whether or not the writer was a human and whatever the issue's
|
|
101
|
-
route. The
|
|
102
|
-
|
|
81
|
+
route. The output says so (`You follow this ask: its answer and replies reach you directly.`) once per ask.
|
|
82
|
+
Leave a thread you no longer need, or rejoin one, with:
|
|
103
83
|
|
|
104
|
-
```
|
|
105
|
-
|
|
84
|
+
```bash
|
|
85
|
+
dispatch follow --ask <id> --action unfollow # or --action follow
|
|
106
86
|
```
|
|
107
87
|
|
|
108
|
-
|
|
109
|
-
`
|
|
88
|
+
`--ask` is the full ask id or a `dispatch://KEY/ask/<id>` reference; `dispatch follow`, `dispatch edit-ask`, and
|
|
89
|
+
`dispatch resolve-ask` also take an 8+ hex prefix that is unique among your own open asks, and refuse anything shorter by naming
|
|
110
90
|
those asks. A human may also remove you from the ask card; either way you are
|
|
111
91
|
told with an `ask.follower_removed` notice, and a human adding you arrives as `ask.follower_added`.
|
|
112
92
|
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# Editing a document
|
|
2
2
|
|
|
3
|
-
Every document
|
|
4
|
-
with `
|
|
5
|
-
the
|
|
3
|
+
Every document Dispatch holds — an issue's spec, a project document — is edited in place
|
|
4
|
+
with `dispatch doc-edit`, never re-uploaded. "The Spec" in `skill://dispatch` sends you here for
|
|
5
|
+
the command's shape, how to target the text you mean, what each operation costs a block, and how to
|
|
6
6
|
reject a stale edit.
|
|
7
7
|
|
|
8
|
-
```
|
|
9
|
-
|
|
8
|
+
```bash
|
|
9
|
+
dispatch doc-edit --issue <KEY> --artifact spec --summary '<names the version>' --ops-json-file - <<'EOF'
|
|
10
|
+
[{"op": "replace", "find": "old sentence", "with": "new sentence"}]
|
|
11
|
+
EOF
|
|
10
12
|
```
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
`--project` replaces `--issue` for a project document, and `--precondition-json` guards against a
|
|
14
|
+
stale edit (below). It prints whether the edit applied, the version it wrote, which operations
|
|
15
|
+
changed nothing (`unchanged_ops`) or were lost to a concurrent change (`lost_ops`), and the document
|
|
16
|
+
token this edit produced, as a `Document token: <token>` line. The ops are a JSON array of this exact `EditOp` shape:
|
|
14
17
|
|
|
15
18
|
```ts
|
|
16
19
|
type EditOp = {
|
|
@@ -28,8 +31,8 @@ type EditOp = {
|
|
|
28
31
|
};
|
|
29
32
|
```
|
|
30
33
|
|
|
31
|
-
An operation takes only these keys. A key it does not declare is refused before the
|
|
32
|
-
|
|
34
|
+
An operation takes only these keys. A key it does not declare is refused before the command sends
|
|
35
|
+
anything, naming the operation and its keys, because every key but `op` is optional: a
|
|
33
36
|
misspelled `with` would otherwise be dropped and the `replace` would delete the text you meant to
|
|
34
37
|
rewrite.
|
|
35
38
|
|
|
@@ -93,7 +96,7 @@ paragraph is stored `\---`, not a rule, so to add a rule, `insert` it beside the
|
|
|
93
96
|
`***`). A CR LF or a lone carriage return in any text you write - an insert's markdown, a `with` in text or in code,
|
|
94
97
|
a suggestion, an upload or a spec - is stored as a line feed, as the browser editor reads both. Use zero-based
|
|
95
98
|
`occurrence` for a
|
|
96
|
-
repeated target; re-read a missing or ambiguous target before retrying. Pass
|
|
99
|
+
repeated target; re-read a missing or ambiguous target before retrying. Pass `--summary` to name the version when recording a decision.
|
|
97
100
|
|
|
98
101
|
**Rewriting several paragraphs is one `replace` per paragraph, then a read-back.** `replace` is inline:
|
|
99
102
|
each `with` is the new text of one paragraph, and outside a code block a `with` that forms two paragraphs is
|
|
@@ -131,17 +134,17 @@ the old block's place is it a `delete` of the old block and then an `insert` of
|
|
|
131
134
|
block before or after it. The delete is what costs the id (below); a typed block keeps its id when the insert
|
|
132
135
|
carries it, which works only in that order, because an insert carrying an id the document still holds is refused.
|
|
133
136
|
The tools refuse a `delete` or `retype` that would take out an `ask` block whose ask is still open, delete-then-insert included:
|
|
134
|
-
reword it with `replace`, relocate it with `move`, or change its question, options, urgency or `multiple` with `
|
|
137
|
+
reword it with `replace`, relocate it with `move`, or change its question, options, urgency or `multiple` with `dispatch edit-ask` if you asked it. A single
|
|
135
138
|
batch that moves an open block out of a container and then deletes the container is refused; make them two calls (the check reads
|
|
136
139
|
the document as it stood before the batch).
|
|
137
140
|
Then read the document back with
|
|
138
|
-
`
|
|
141
|
+
`dispatch doc-read` and read the passage and its neighbours, not a grep for the words you added: an empty
|
|
139
142
|
`with` deletes the matched text on purpose, so a `replace` whose `with` you meant to fill
|
|
140
143
|
empties that paragraph — the block and its id stay, holding nothing — and only a read shows what the document now says.
|
|
141
144
|
|
|
142
145
|
A batch that leaves the document's semantic identity unchanged — including its inline anchor marks, so an edit that only orphans a
|
|
143
146
|
comment or ask anchor still mints its version — mints no version, named or not: the response carries
|
|
144
|
-
`changed: false` with `unchanged_ops` naming each operation that did nothing, and the
|
|
147
|
+
`changed: false` with `unchanged_ops` naming each operation that did nothing, and the output says nothing changed. A `--summary`
|
|
145
148
|
does not force a version for such a batch; `POST /api/v1/artifacts/<id>/versions`, which names the current state on purpose, still does.
|
|
146
149
|
|
|
147
150
|
A `delete` whose `find` is a block's entire text removes the block itself — the bullet, paragraph, or heading, not just its words — and
|
|
@@ -165,11 +168,11 @@ whose anchor lies inside the moved block, or a delete that would leave a typed b
|
|
|
165
168
|
`INVALID_OP` naming the field and the rule.
|
|
166
169
|
|
|
167
170
|
`GET /api/v1/artifacts/<artifact UUID>/blocks` includes a full-state `token` on every block, including
|
|
168
|
-
inline marks. To reject a stale edit, pass
|
|
169
|
-
`{
|
|
170
|
-
`{
|
|
171
|
-
`
|
|
172
|
-
own edit produced: a run of guarded edits passes each
|
|
171
|
+
inline marks. To reject a stale edit, pass `--precondition-json` with exactly one of
|
|
172
|
+
`{"document": "<document token>"}` or
|
|
173
|
+
`{"blocks": [{"id": "<block id>", "token": "<block token>"}]}`. A document token comes from
|
|
174
|
+
`dispatch doc-read` or from the previous `dispatch doc-edit`, whose output carries the token its
|
|
175
|
+
own edit produced: a run of guarded edits passes each output's token to the next one and reads the
|
|
173
176
|
document once, not once per edit. The server resolves the whole batch before
|
|
174
177
|
mutation: a block guard must cover every content block it changes, or Dispatch returns
|
|
175
178
|
`400 INVALID_PRECONDITION` without applying anything. Use a document token for insert and move because they
|
|
@@ -197,6 +200,6 @@ an existing paragraph is the question that should become a decision.
|
|
|
197
200
|
|
|
198
201
|
An ask block has two ids: the block id, shown as `:::ask{#<id> …}` in the rendered document and
|
|
199
202
|
taken bare by `move`/`delete` in `block` (the `block:<id>` form is only for `before`/`after`
|
|
200
|
-
anchors), and the ask id, which `
|
|
201
|
-
`?ask=`), `
|
|
203
|
+
anchors), and the ask id, which `dispatch open-asks`, the dashboard's ask links (`/asks/<id>`,
|
|
204
|
+
`?ask=`), `dispatch read` and `dispatch comment --reply-to-ask` use. They differ;
|
|
202
205
|
`dispatch://KEY/ask/<block-id>` answers `not found`.
|
|
@@ -15,7 +15,7 @@ Dispatch writes its fences that way. An unclosed typed block at document level i
|
|
|
15
15
|
opening line that continues a paragraph instead of standing on its own (indented four or more
|
|
16
16
|
columns under the paragraph's text) is refused, naming the line's number and text - `INVALID_OP` on an edit's `markdown` or `with`, `INVALID_MARKDOWN` on any other write - since it
|
|
17
17
|
would be stored as the paragraph's text; start the block on its own line. An opening written inside
|
|
18
|
-
a line is stored as text, and `
|
|
18
|
+
a line is stored as text, and `dispatch issue` and `dispatch artifact` quote it back as a
|
|
19
19
|
typed-block opening that is text, not a block. For
|
|
20
20
|
a new typed block, omit `#block-id`; Dispatch mints it. When editing an existing typed block, retain
|
|
21
21
|
its id and every rendered attribute. Never copy an existing block's id into new markdown: an id
|
|
@@ -24,9 +24,9 @@ outside the text it replaces is refused naming the id: `INVALID_OP` for an inser
|
|
|
24
24
|
`INVALID_MARKDOWN` for any other write. To rewrite such a block whole, `delete` it and then
|
|
25
25
|
`insert` the new one carrying its id, anchored on the block before or after it, in that order and
|
|
26
26
|
in one batch: an insert carrying an id the document still holds is refused. An `ask` block whose ask
|
|
27
|
-
is still open cannot be rewritten that way:
|
|
27
|
+
is still open cannot be rewritten that way: `dispatch doc-edit` refuses the `delete`, so reword it with
|
|
28
28
|
`replace`, relocate it with `move`, or change its question, options, urgency or `multiple` with
|
|
29
|
-
`
|
|
29
|
+
`dispatch edit-ask` if you asked it ([Editing a document](skill://dispatch/references/document-edits.md)).
|
|
30
30
|
|
|
31
31
|
Use only the type names, content rule, attributes, and enum values returned by the schema. Values are
|
|
32
32
|
quoted: `:::callout{kind="warning" title="Risk"}`. Do not write Pandoc-style `::: {.callout}`, leaf
|
|
@@ -55,67 +55,67 @@ unknown cost before production while keeping today's release possible.
|
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
When a human answers a decision written as an ask block, the answer lives on that ask. Use
|
|
58
|
-
`
|
|
58
|
+
`dispatch resolve-ask` when the decision is resolved without a human response, or preserve the
|
|
59
59
|
human's answer; never rewrite the question into its answer or blank its options. An edit that leaves
|
|
60
60
|
an ask block without a question or with a blank option is rejected with `INVALID_ASK_BLOCK`.
|
|
61
61
|
|
|
62
|
-
When `
|
|
62
|
+
When `dispatch issue` or `dispatch artifact` answers `This spec holds no ask blocks …`, read it as a
|
|
63
63
|
question: either no decision is needed and you say nothing, or you forgot to make it a block. When
|
|
64
64
|
it answers `… typed-block openings in this document are text, not blocks`, the quoted openings are
|
|
65
65
|
blocks stored as prose (inside a line, or a paste with something before every line): fix the markdown
|
|
66
66
|
and upload again; a mention on purpose belongs in code. Neither answer sees a spec wrapped whole in a
|
|
67
67
|
code fence (take the fence off), a malformed opening inside a line (`::ask{`, `:::ask {`: an ask opens
|
|
68
|
-
only as `:::ask{…}` on a line of its own), or any `
|
|
69
|
-
ask, `
|
|
68
|
+
only as `:::ask{…}` on a line of its own), or any `dispatch doc-edit`: after an edit that writes an
|
|
69
|
+
ask, `dispatch doc-read` the section and check it renders as `:::ask{#<id> …}` on its own line.
|
|
70
70
|
|
|
71
71
|
## Comments and suggestions
|
|
72
72
|
|
|
73
|
-
Add feedback with:
|
|
73
|
+
Add feedback with `dispatch comment` (`dispatch comment --help` lists its flags):
|
|
74
74
|
|
|
75
|
-
```
|
|
76
|
-
|
|
75
|
+
```bash
|
|
76
|
+
dispatch comment --issue <KEY> --artifact spec --quote '<the passage>' --body '<the question or note>'
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
It
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
for display. Omit both for a floating issue comment. A reply (`
|
|
84
|
-
|
|
79
|
+
It prints the comment's id; a `--reply-to-ask` reply also makes you one of the ask's followers
|
|
80
|
+
(see [Following](skill://dispatch/references/asks.md)).
|
|
81
|
+
`--ref` names the owner (an issue or project-document reference) in place of `--issue`/`--project`.
|
|
82
|
+
`--quote` requires `--artifact`; its anchor is pinned to the containing block while retaining the quote
|
|
83
|
+
for display. Omit both for a floating issue comment. A reply (`--reply-to`/`--reply-to-ask`) takes no
|
|
84
|
+
`--quote`; it belongs to its parent's anchor. Reply to any comment in a thread; the server keeps
|
|
85
85
|
threads flat. A reply to a resolved thread reopens it, except a decided suggestion's: a reply joins
|
|
86
|
-
that thread and the suggestion stays accepted or rejected. Use `
|
|
87
|
-
question asked with `
|
|
86
|
+
that thread and the suggestion stays accepted or rejected. Use `--reply-to-ask` to reply directly under a
|
|
87
|
+
question asked with `dispatch ask`; `--turn` (only with `--reply-to-ask`) says who holds the turn after
|
|
88
88
|
the reply — `agent` for a progress note that keeps the ask waiting on you, `human` (the default) when
|
|
89
89
|
the human needs to act; see "Asking" in `skill://dispatch`. Comments are edited only by their author from the
|
|
90
90
|
dashboard. A delivered `comment.created` event carries the comment `id`; reply to it with
|
|
91
|
-
`
|
|
91
|
+
`dispatch comment --reply-to <id>`.
|
|
92
92
|
|
|
93
93
|
Resolve your own review comment once you have addressed it:
|
|
94
94
|
|
|
95
|
-
```
|
|
96
|
-
|
|
95
|
+
```bash
|
|
96
|
+
dispatch resolve-comment --comment <id>
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
8+ character id prefix is resolved against the owner's comments). It
|
|
101
|
-
say what you did in a `
|
|
99
|
+
`--comment` is the comment id, or a `dispatch://KEY/comment/<id>` or `dispatch://PROJECT/artifact/<slug>/comment/<id>` reference (an
|
|
100
|
+
8+ character id prefix is resolved against the owner's comments). It takes no reason —
|
|
101
|
+
say what you did in a `--reply-to` first if the thread needs it. The server lets any session or human resolve any open comment, so
|
|
102
102
|
resolve only threads you opened or were asked to close; reopening a resolved thread is human-only (from the dashboard), though your
|
|
103
103
|
reply to it reopens it - except a decided suggestion's, which your reply joins and leaves accepted or rejected. A reply to a pending
|
|
104
|
-
suggestion whose text an edit removed lands as well. Asks are closed with `
|
|
104
|
+
suggestion whose text an edit removed lands as well. Asks are closed with `dispatch resolve-ask` instead.
|
|
105
105
|
|
|
106
|
-
An exact replacement for document text is a suggestion (`
|
|
106
|
+
An exact replacement for document text is a suggestion (`dispatch suggest`), never a comment; a
|
|
107
107
|
comment is for a question or a note the human answers in words. A human accepts a suggestion with
|
|
108
108
|
one click and cannot accept a comment, so propose the replacement instead of describing it:
|
|
109
109
|
|
|
110
|
-
```
|
|
111
|
-
|
|
110
|
+
```bash
|
|
111
|
+
dispatch suggest --issue <KEY> --artifact spec --quote '<exact text>' --replace-with '<replacement>'
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
It
|
|
115
|
-
Errors: `TARGET_AMBIGUOUS` (add
|
|
114
|
+
It prints the suggestion's id; `--body` adds a note and `--occurrence` picks a repeated quote. A human accepts or rejects a suggestion.
|
|
115
|
+
Errors: `TARGET_AMBIGUOUS` (add `--occurrence`), `TARGET_NOT_FOUND` (re-read first), `INVALID_ANCHOR`/`ANCHOR_MISSING`/`ANCHOR_ORPHANED`
|
|
116
116
|
(bad, unwritten, or stale quote), `INVALID_MARKDOWN`/`DOC_SCHEMA` (malformed content), `CAP_EXCEEDED`, `ISSUE_CLOSED`.
|
|
117
117
|
Suggest only what the quoted block can hold. The accept, not the suggestion, checks that: an
|
|
118
|
-
accept whose
|
|
118
|
+
accept whose replacement would break an ask block that was readable before it is refused with
|
|
119
119
|
`INVALID_ASK_BLOCK` - a question given a code block, text after an ask's options, a second option
|
|
120
120
|
list, or an emptied question; one that names an id the document holds outside the text it
|
|
121
121
|
replaces, an ask under a held id included, with `INVALID_MARKDOWN`; and one no part of the
|
|
@@ -127,51 +127,54 @@ stays open until someone rejects or replaces it.
|
|
|
127
127
|
|
|
128
128
|
Attach an image, diagram, or local file with:
|
|
129
129
|
|
|
130
|
-
```
|
|
131
|
-
|
|
130
|
+
```bash
|
|
131
|
+
dispatch artifact --issue <KEY> --name diagram.png --path ./diagram.png
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
Or, when the text is already
|
|
134
|
+
Or, when the text is already at hand, post a Markdown document directly:
|
|
135
135
|
|
|
136
|
-
```
|
|
137
|
-
|
|
136
|
+
```bash
|
|
137
|
+
dispatch artifact --issue <KEY> --name load-test-results.md --content-file - <<'EOF'
|
|
138
|
+
# Load test
|
|
139
|
+
...
|
|
140
|
+
EOF
|
|
138
141
|
```
|
|
139
142
|
|
|
140
|
-
Exactly one of
|
|
141
|
-
Exactly one of
|
|
142
|
-
Uploading the same
|
|
143
|
-
with your text. Never do that: the spec is edited in place with `
|
|
144
|
-
artifact by the slug
|
|
143
|
+
Exactly one of `--issue` and `--project` is required. A project upload creates an unlinked project document; it takes no `--artifact`.
|
|
144
|
+
Exactly one of `--path` and `--content` is required. It prints the document's slug and version.
|
|
145
|
+
Uploading the same `--name` creates its next version — so uploading `spec.md` **replaces the issue's own specification**
|
|
146
|
+
with your text. Never do that: the spec is edited in place with `dispatch doc-edit` (see [Editing a document](skill://dispatch/references/document-edits.md)). Address an existing
|
|
147
|
+
artifact by the slug the upload printed or by its filename, and a project document by its artifact id, slug, or filename; the
|
|
145
148
|
slug also arrives on `artifact.created` events. Dispatch suffixes a slug two documents would share, so one document's
|
|
146
149
|
filename can be another's slug (`plan v2` takes `plan-v2`, then a document named `plan-v2` takes `plan-v2-2`): a bare
|
|
147
|
-
|
|
150
|
+
`--artifact` that names both is refused with each one's id, while a `dispatch://` reference's document part is always the slug.
|
|
148
151
|
|
|
149
|
-
A picture meant to be seen inline in a message, comment or ask is not uploaded with `
|
|
150
|
-
path
|
|
152
|
+
A picture meant to be seen inline in a message, comment or ask is not uploaded with `dispatch artifact`: pass its local
|
|
153
|
+
path with that command's `--image`, once per picture (PNG, JPEG, GIF or WebP by its bytes, at most 25 MiB each). Each is uploaded to the issue (a
|
|
151
154
|
project document's project; for a reply to a direct message, your own conversation) and appended after a blank line as
|
|
152
155
|
one `` line, about 60 characters that count toward the body or
|
|
153
|
-
question cap; a
|
|
156
|
+
question cap; a command the lines would carry over the cap is refused with the count before anything uploads, and again,
|
|
154
157
|
with nothing posted, in the rare case where Dispatch gives an upload a longer address than that (a later version of a
|
|
155
158
|
name the owner already holds, or a slug another file took first). The `@vN` pins the version the upload made (the same
|
|
156
159
|
file name again makes the next version). A plain `dispatch://KEY/artifact/<slug>` reference to an image stays a link
|
|
157
160
|
with a thumbnail.
|
|
158
161
|
|
|
159
|
-
`
|
|
160
|
-
10 MiB per read, and its `Pictures:` section names each one shown, in order, and the rest by reference for
|
|
161
|
-
`
|
|
162
|
-
larger one or an SVG is described). A picture in a
|
|
162
|
+
`dispatch read` writes the pictures the messages, asks and comments it shows embed to files, newest first, at most 8 and
|
|
163
|
+
10 MiB per read, prints a `- picture: <path>` line for each, and its `Pictures:` section names each one shown, in order, and the rest by reference for
|
|
164
|
+
`dispatch doc-read`, which shows one picture (at most 3,750,000 bytes, the 5 MB of base64 a model provider takes; a
|
|
165
|
+
larger one or an SVG is described). Open each written file with your file-read tool. A picture in a
|
|
163
166
|
conversation on the Agents page belongs to that conversation, `dispatch://agent/<session id>/artifact/<slug>@vN`, and
|
|
164
|
-
`
|
|
167
|
+
`dispatch doc-read` reads it by that reference alone. On Oh My Pi an Inbox delivery carries its pictures as images; in
|
|
165
168
|
Claude Code it stays text with the reference.
|
|
166
169
|
|
|
167
170
|
A session is shown each picture once. A later read or delivery that embeds a picture you were already shown names it in
|
|
168
171
|
`Pictures:` as `shown earlier this session` and sends no bytes, since every request carries the session's whole history
|
|
169
|
-
and a model provider refuses one over 32 MB; `
|
|
172
|
+
and a model provider refuses one over 32 MB; `dispatch doc-read` always shows the picture, so ask it for one you need
|
|
170
173
|
again, after compaction too.
|
|
171
174
|
|
|
172
175
|
Documents are CommonMark. A bare `<https://example.com|text>` is a CommonMark autolink and is normalised: the angle brackets are
|
|
173
176
|
dropped and the URL keeps `|text`. A backslash-escaped `\<https://example.com|text>` displays as `<https://example.com|text>` in the
|
|
174
|
-
document but comes back re-escaped (`\<`) from `
|
|
177
|
+
document but comes back re-escaped (`\<`) from `dispatch doc-read`. A Slack mrkdwn draft, or any other payload that is not Markdown,
|
|
175
178
|
still belongs inside a fenced code block, where it survives verbatim both ways.
|
|
176
179
|
|
|
177
180
|
A table cell ends at every `|` not written `\|`, inside inline code and links too, so write
|
|
@@ -184,27 +187,27 @@ of bare table rows `TABLE_WIDTH`, which names the cell counts only.
|
|
|
184
187
|
|
|
185
188
|
## Approval requests
|
|
186
189
|
|
|
187
|
-
```
|
|
188
|
-
|
|
190
|
+
```bash
|
|
191
|
+
dispatch request-approval --issue <KEY> --summary '<what the human is approving>'
|
|
189
192
|
```
|
|
190
193
|
|
|
191
|
-
The
|
|
192
|
-
"Approve spec.md (version N)?" followed by
|
|
194
|
+
The command opens an approval ask with the options `Approve` and `Request changes`, its question
|
|
195
|
+
"Approve spec.md (version N)?" followed by the summary, where N is the document's latest version. It
|
|
193
196
|
is refused, with nothing sent, while that version holds a decision block open, and the refusal
|
|
194
|
-
names each block and its ask. An answer or a `
|
|
197
|
+
names each block and its ask. An answer or a `dispatch resolve-ask` closes the ask at once but
|
|
195
198
|
reaches a version only when the document settles, about two seconds later, or with your next
|
|
196
|
-
`
|
|
199
|
+
`dispatch doc-edit`: fold the answer into the text (or, for a waiver, write the human's decision
|
|
197
200
|
in) before you request. A block written in the last few seconds counts as open before Dispatch has
|
|
198
201
|
opened its ask. A document holds one open request. A new version moves it to that version, keeping
|
|
199
202
|
its thread and summary, and leaves it waiting on you, as a human's reply in its thread does; a move
|
|
200
|
-
your own edit made sends you no event, and `
|
|
201
|
-
`Approval: awaiting, waiting on agent`.
|
|
202
|
-
allows: that hands the same request back to the human, reworded first when
|
|
203
|
-
own reply in its thread hands it back too, with no
|
|
204
|
-
you post it with `
|
|
203
|
+
your own edit made sends you no event, and `dispatch read` and `dispatch doc-read` show it as
|
|
204
|
+
`Approval: awaiting, waiting on agent`. Run it again when "Approval of a spec" in `skill://dispatch`
|
|
205
|
+
allows: that hands the same request back to the human, reworded first when `--summary` is new. Your
|
|
206
|
+
own reply in its thread hands it back too, with no command and the summary it already holds, unless
|
|
207
|
+
you post it with `--reply-to-ask` and `--turn agent` (`--reply-to` carries no turn, so its reply takes
|
|
205
208
|
the default, `human`) or a new version has moved the request since your last
|
|
206
|
-
`
|
|
207
|
-
nothing, and
|
|
209
|
+
`dispatch request-approval`. While it waits on the human, the same `--summary` changes
|
|
210
|
+
nothing, and a different `--summary` is refused, since it would rewrite the card they are
|
|
208
211
|
reading. The answer reaches you as `artifact.approved` or `artifact.changes_requested` with the
|
|
209
212
|
pinned `version` and closes the request, so the next call opens a new one; `changes_requested`
|
|
210
213
|
carries the reason, which is your next piece of work. Those reads show the document's approval
|
|
@@ -213,18 +216,18 @@ state; `stale` means it was approved and then edited.
|
|
|
213
216
|
## A document that is reloading
|
|
214
217
|
|
|
215
218
|
These calls can answer `DOC_SERVICE_UNAVAILABLE` (HTTP 503), because each writes a document inside its
|
|
216
|
-
transaction: `
|
|
217
|
-
in a thread whose first comment is anchored; `
|
|
218
|
-
comment; `
|
|
219
|
-
block, `
|
|
220
|
-
uploading a new document, `
|
|
221
|
-
`
|
|
219
|
+
transaction: `dispatch doc-edit`; `dispatch ask` and `dispatch comment` on a quote; a `dispatch comment` reply
|
|
220
|
+
in a thread whose first comment is anchored; `dispatch suggest`; `dispatch resolve-comment` on an anchored
|
|
221
|
+
comment; `dispatch artifact` replacing a document that already exists; and, on an ask that lives in a `:::ask`
|
|
222
|
+
block, `dispatch edit-ask` and `dispatch resolve-ask`, which write that block. Creating an issue with a spec,
|
|
223
|
+
uploading a new document, `dispatch request-approval` and `dispatch message` never answer it, and neither do
|
|
224
|
+
`dispatch edit-ask` and `dispatch resolve-ask` on an ask that has no block. It means that document's live room
|
|
222
225
|
failed and is reloading from its durable copy, so the server refused rather than wait for it; your call wrote
|
|
223
226
|
nothing and the document is intact. Nothing retries it for you: the Dispatch client hands a 503 straight back.
|
|
224
227
|
Wait a few seconds and make the same call again. A second refusal in a row is worth telling your human about,
|
|
225
228
|
with the document's reference.
|
|
226
229
|
|
|
227
|
-
`
|
|
230
|
+
`dispatch doc-read` can answer it too, though it writes nothing: a read never opens a live room, and waits out
|
|
228
231
|
a room that is reloading, so it is refused only when the document's durable copy cannot be read or decoded.
|
|
229
232
|
Retry it the same way.
|
|
230
233
|
|