@sjawhar/opencode-legion-envoy 3.13.0 → 3.14.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 +21 -0
- package/package.json +1 -1
- package/skills/AGENTS.md +2 -0
- package/skills/dispatch/SKILL.md +83 -663
- package/skills/dispatch/references/api.md +28 -0
- package/skills/dispatch/references/asks.md +109 -0
- package/skills/dispatch/references/document-edits.md +1 -1
- package/skills/dispatch/references/documents.md +148 -0
- package/skills/dispatch/references/examples.md +82 -0
- package/skills/dispatch/references/issues.md +213 -0
- package/skills/dispatch/references/messages.md +65 -0
- package/skills/dispatch/references/reading.md +55 -0
- package/skills/dispatch-first/SKILL.md +49 -0
- package/skills/legion-architect/SKILL.md +2 -2
- package/skills/legion-worker/SKILL.md +65 -365
- package/skills/legion-worker/references/conflicts-and-rewrites.md +129 -0
- package/skills/legion-worker/references/merge-gate.md +101 -0
- package/skills/legion-worker/references/pr-body.md +125 -0
- package/skills/legion-worker/references/review-threads.md +71 -0
- package/src/server.ts +22 -1
- package/skills/legion-worker/references/knowledge-injection.md +0 -98
- /package/skills/legion-worker/{resources/strategies → references}/cleanup-deletion.md +0 -0
- /package/skills/legion-worker/{resources/strategies → references}/systematic-rename.md +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Answering targeted and direct messages
|
|
2
|
+
|
|
3
|
+
`skill://dispatch` sends you here when a Dispatch frame targets you as BTW, Aside or Steer, or a
|
|
4
|
+
human messages you directly from the Agents page.
|
|
5
|
+
|
|
6
|
+
## Targeted agent messages
|
|
7
|
+
|
|
8
|
+
A human — or any bearer caller over HTTP, such as a test rig — can target the issue message at a
|
|
9
|
+
live Envoy session or role as **BTW**, **Aside**, or **Steer**. The incoming Dispatch frame names
|
|
10
|
+
the issue and includes a `reply_with` hint (`{ tool, args }`, ready to issue on any host); reply on the same open issue with the existing
|
|
11
|
+
tool, never a new targeted send:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
dispatch_message({
|
|
15
|
+
issue: "CORE-1",
|
|
16
|
+
in_reply_to: "<targeted-message-id>",
|
|
17
|
+
body: "The requested answer.",
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`in_reply_to` correlates the answer under the asker's message in its Conversation card. A BTW
|
|
22
|
+
delivery can post its answer automatically; use this call when the frame asks the primary agent to
|
|
23
|
+
reply. A human may reply to your message in turn — the follow-up arrives as a targeted frame whose
|
|
24
|
+
`in_reply_to` names your message and whose `reply_body` quotes it; answer it the same way,
|
|
25
|
+
`dispatch_message({ issue, in_reply_to: "<their reply id>", body })`, so the exchange reads as one
|
|
26
|
+
thread. `dispatch_message` itself never carries `target` or `delivery`: agent-to-agent traffic goes
|
|
27
|
+
through Envoy or the hub. A bearer that targets over HTTP names its own session in `actor`
|
|
28
|
+
(`{kind: "session", id}`), and the card shows that session as the author. `GET /api/v1/agents`
|
|
29
|
+
(any authenticated caller) lists live sessions with their capabilities (`aside`, `btw`, `steer`);
|
|
30
|
+
target only a session that advertises the mode you want. Sending to a session with no issue
|
|
31
|
+
(`POST /api/v1/agents/{session_id}/messages`) stays human-only.
|
|
32
|
+
|
|
33
|
+
## Answering a direct message
|
|
34
|
+
|
|
35
|
+
A human can also message you directly from the **Agents** page, with no issue at all. That frame
|
|
36
|
+
names no issue and its `reply_with` hint carries none either; answer it with the message's bare
|
|
37
|
+
id in `in_reply_to`, alone:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
dispatch_message({
|
|
41
|
+
in_reply_to: "<the direct message's id>",
|
|
42
|
+
body: "The requested answer.",
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Leave `issue` out — there is no issue to post into, and naming one would file your answer on
|
|
47
|
+
unrelated work. Dispatch threads the reply under their message in the same conversation, and the
|
|
48
|
+
human sees it in your conversation on the Agents page, where it shows as an unread reply until
|
|
49
|
+
they read it. Every other message still names its issue, so keep the `issue`
|
|
50
|
+
the frame gave you whenever it gave you one; a `dispatch://KEY/message/<id>` reference names the
|
|
51
|
+
issue its message lives on, so that form is a reply on that issue, not a direct message.
|
|
52
|
+
|
|
53
|
+
Have more to say after you answered? Call it again with the same `in_reply_to` and the new text:
|
|
54
|
+
Dispatch threads that follow-up under your first reply, and the tool result names the reply it
|
|
55
|
+
follows. The same text again posts nothing, so a retry is safe. Your host may already have
|
|
56
|
+
answered a **BTW** automatically before you got here; a second call is then your follow-up to
|
|
57
|
+
that answer, so read the result before writing again.
|
|
58
|
+
|
|
59
|
+
Read the whole conversation back — their message and every reply, yours included — with the
|
|
60
|
+
message id alone; it has no issue:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
dispatch_read({ message: "<the direct message's id, or any reply's>" })
|
|
64
|
+
```
|
|
65
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Reading Dispatch back, and the reference forms
|
|
2
|
+
|
|
3
|
+
`skill://dispatch` sends you here when you catch up after a restart, read an issue, ask, comment,
|
|
4
|
+
message or document, trace what cites a node, or need the exact `dispatch://` form for a reference.
|
|
5
|
+
|
|
6
|
+
## What comes back
|
|
7
|
+
|
|
8
|
+
After a restart, catch up with:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
dispatch_read({ issue?, project?, artifact?, ref? })
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
With an issue ref, it returns the issue summary, open asks, references, and recent events with `details` `{ issue }`. With a project
|
|
15
|
+
document owner or ref, it returns a document summary with `details` `{ project, document }`. With an ask ref, it returns that ask's
|
|
16
|
+
question, options, state, answer, and its reply thread. With a comment ref, it returns that comment and its quoted reply chain. With a
|
|
17
|
+
message ref, it returns that message and its reply chain. Reads do not subscribe; use `dispatch_doc_read` for document contents.
|
|
18
|
+
|
|
19
|
+
Every read ends with two sections from the reference graph. `Referenced by:` lists what points at the node — every document, ask,
|
|
20
|
+
comment, or message that cites it, plus its structure: child issues, attached documents, anchored and owned asks and comments, replies,
|
|
21
|
+
followers — and `Links:` lists what it cites. Each row is `- <edge kind> <node kind> dispatch://… (<excerpt> · <when>)`; for a
|
|
22
|
+
document source the excerpt is the start of the block holding the mention, and a whole list is one block, so every issue named in
|
|
23
|
+
one list previews the list's first item. When a document references many issues and each backlink should read right, give each
|
|
24
|
+
issue its own paragraph (or block), not an item of one list. Cross-project, always: a message on another project's issue that
|
|
25
|
+
cites an ask shows up under that ask. So "what led to this decision" is one `dispatch_read` on the ask, and "who relies on this
|
|
26
|
+
document" one read on the document. Cite with `dispatch://` references (below) whenever you name a node in a body — a bare id or
|
|
27
|
+
title is invisible to the graph.
|
|
28
|
+
|
|
29
|
+
## Reference forms
|
|
30
|
+
|
|
31
|
+
Use these in document, ask, comment, and message bodies. In the dashboard, a reference renders
|
|
32
|
+
as an inline link whose text is the target's title (an issue's title, an ask's question, a
|
|
33
|
+
comment's first line, a document's name) once it resolves; a body that is only a bare reference
|
|
34
|
+
still gets an unfurl card instead. Every `ref` argument below (and `issue`/`project`) accepts
|
|
35
|
+
either form — an issue key or a project key is never ambiguous, since a project key never
|
|
36
|
+
contains a dash:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
dispatch://KEY
|
|
40
|
+
dispatch://KEY/spec
|
|
41
|
+
dispatch://KEY/artifact/<slug>[@vN]
|
|
42
|
+
dispatch://KEY/ask/<id>
|
|
43
|
+
dispatch://KEY/comment/<id>
|
|
44
|
+
dispatch://KEY/message/<id>
|
|
45
|
+
dispatch://PROJECT/artifact/<document-ref>[@vN]
|
|
46
|
+
dispatch://PROJECT/artifact/<document-ref>/ask/<id>
|
|
47
|
+
dispatch://PROJECT/artifact/<document-ref>/comment/<id>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A bare UUID or `KEY#seq` is not a reference; the `dispatch://` form is what Dispatch links and records. `dispatch_read` also
|
|
51
|
+
accepts the dashboard URL of an issue, spec, artifact, ask, comment, or project document on the configured server (it maps to the
|
|
52
|
+
`dispatch://` form above), and an ask or comment id may be a unique prefix of at least 8 hex characters; a message id is always the
|
|
53
|
+
full uuid. A non-uuid id on `GET /asks/{id}`, `/comments/{id}`, or `/issues/{key}/messages/{id}` is a 400 `ASK_ID_INPUT` /
|
|
54
|
+
`COMMENT_ID_INPUT` / `MESSAGE_ID_INPUT`, never a 500.
|
|
55
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dispatch-first
|
|
3
|
+
description: "Use in any session with Dispatch tools, before planning, filing an issue, asking a human, posting a finding, or starting work that someone may already track or have decided."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dispatch first
|
|
7
|
+
|
|
8
|
+
Dispatch already holds most of what you are about to plan, file or ask: the open issues, their
|
|
9
|
+
specs, and the answers humans gave. A second issue for tracked work, or a question a human already
|
|
10
|
+
answered, costs that human the time to notice it and splits the history across two places.
|
|
11
|
+
|
|
12
|
+
## Search before you act
|
|
13
|
+
|
|
14
|
+
Before you plan, file an issue, ask, post a finding or start work, search Dispatch. Every word of
|
|
15
|
+
the query must match, so each word you add can only lose hits: search with two or three words, the
|
|
16
|
+
thing and what is wrong with it, as a user would name them. Never paste a draft.
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
dispatch_search({ query: "broadcast send order" })
|
|
20
|
+
dispatch_search({ query: "reviewer threads OR review comments" })
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
When a query finds nothing, drop a word before you add one. Try two or three wordings (the
|
|
24
|
+
component's name, the symptom, the fix) before you conclude that nothing exists. Open every hit
|
|
25
|
+
that could be yours with `dispatch_read`, then its parent (the `child_of` row under `Links:`); the
|
|
26
|
+
parent's children and the issue's `Components:` line show where the rest of that work lives.
|
|
27
|
+
|
|
28
|
+
## What to do with what you find
|
|
29
|
+
|
|
30
|
+
- **The work is already tracked: extend that issue.** Put the finding on it (a comment, a message,
|
|
31
|
+
or an edit to its spec) instead of filing another. File a new issue only when no hit covers the
|
|
32
|
+
work, and cite the nearest one you ruled out (`dispatch://KEY`).
|
|
33
|
+
- **The question is already decided: cite the decision.** An answered ask is the record. Point to
|
|
34
|
+
it where you rely on it (`dispatch://KEY/ask/<id>`) instead of asking again.
|
|
35
|
+
- **You met a duplicate: close it.** Keep the issue that holds the spec and the discussion, carry
|
|
36
|
+
over anything only the duplicate has, then close the duplicate with a reason that names the
|
|
37
|
+
survivor: `dispatch_issue_update({ issue, status: "done", reason: "Duplicate of dispatch://KEY." })`.
|
|
38
|
+
When the duplicate carries the `legion` label, or another session or a human holds its claim,
|
|
39
|
+
comment on it naming the survivor instead of closing it.
|
|
40
|
+
- **Every ask and message stands on its own.** The person who answers sees only that text: put the
|
|
41
|
+
facts, the options and your recommendation in it, and link what you cite (`dispatch://…`)
|
|
42
|
+
instead of writing "see above" or "my earlier message".
|
|
43
|
+
|
|
44
|
+
## Load the full skill before you write
|
|
45
|
+
|
|
46
|
+
- **Before you write or change a spec, read `skill://dispatch`,** including its "Writing a spec"
|
|
47
|
+
section.
|
|
48
|
+
- Before any other write to Dispatch (an ask, a message, a comment, a document edit, a status
|
|
49
|
+
change, a claim), load `skill://dispatch` unless you already have in this session.
|
|
@@ -256,10 +256,10 @@ Preserve this order exactly:
|
|
|
256
256
|
|
|
257
257
|
What returns the tree to review: a changed diff — a commit above the approved head that
|
|
258
258
|
touches anything outside `docs/solutions/`, or a conflict-resolution merge whose fingerprint
|
|
259
|
-
(`skill://legion-worker`
|
|
259
|
+
(the unchanged-diff check, `skill://legion-worker/references/conflicts-and-rewrites.md`) differs from the approved head's. What does not: retro's
|
|
260
260
|
`docs/solutions/` commit, and a merge forced by a GitHub-reported conflict whose fingerprint
|
|
261
261
|
is unchanged. For that merge the order is: the implementer merges the bookmark forward with the
|
|
262
|
-
destination (
|
|
262
|
+
destination (the forward-merge procedure in `skill://legion-worker/references/conflicts-and-rewrites.md` — `jj new legion/<KEY> <destination>`,
|
|
263
263
|
never a rebase, since a rebase rewrites every descendant of the chain's fork point, including
|
|
264
264
|
another tree's branch stacked on it), pushes it with the ordinary push procedure (a genuine
|
|
265
265
|
fast-forward), and posts the before/after fingerprints; the tester re-runs the bare gates only;
|