@sjawhar/opencode-legion-envoy 5.11.2 → 6.0.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
CHANGED
|
@@ -15809,7 +15809,7 @@ function followsAsk(owner) {
|
|
|
15809
15809
|
return `You follow this ask: its answer and replies reach you directly. For every event on ${owner.label}: envoy_subscribe ${owner.topic}`;
|
|
15810
15810
|
}
|
|
15811
15811
|
var triageAdviceShown = new Set;
|
|
15812
|
-
var SPEC_CHECK_REMINDER = 'Has a fresh reader checked this spec? Each claim about how a system works today should trace to code read or a command run, and each requirement to the human\'s words or a cited fact. If not, have a fresh read-only subagent
|
|
15812
|
+
var SPEC_CHECK_REMINDER = 'Has a fresh reader checked this spec? Each claim about how a system works today should trace to code read or a command run, and each requirement to the human\'s words or a cited fact. If not, have a fresh read-only subagent check it now and fix what it finds: on Oh My Pi, `task(agent="scout")`, or whatever read-only agent your host bundles; a Legion architect\'s own spec uses the Legion plugin\'s `plan-gap-analyst` agent instead, which only a Legion session has. See the `dispatch-first` skill, "Design in the spec".';
|
|
15813
15813
|
function renderAdvice(tool, key, advice, opts) {
|
|
15814
15814
|
if (advice === undefined)
|
|
15815
15815
|
return [];
|
package/package.json
CHANGED
package/skills/AGENTS.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Skills Layer
|
|
2
2
|
|
|
3
3
|
Legion skills guide the architect and its sequential phase workers in a shared issue workspace.
|
|
4
|
-
They are Markdown instructions loaded by Oh My Pi sessions; the daemon and
|
|
5
|
-
event intake, process lifecycle, credentials, and role delivery.
|
|
4
|
+
They are Markdown instructions loaded by Oh My Pi sessions; the daemon and the two Oh My Pi plugins
|
|
5
|
+
(`packages/pi-envoy`, `packages/pi-legion`) own event intake, process lifecycle, credentials, and role delivery.
|
|
6
6
|
|
|
7
7
|
| Skill | Who reads it | What it owns |
|
|
8
8
|
| --- | --- | --- |
|
|
@@ -20,8 +20,9 @@ event intake, process lifecycle, credentials, and role delivery.
|
|
|
20
20
|
| `thermonuclear-deep-review/` | the `thermonuclear-deep-review` agent, and the reviewer (the Security Guidelines) | the correctness rubric of the reviewer's pair, with its tagged, diff-triggered Security Guidelines and the attack on the PR body's claims (adapted from the MIT-licensed Thermos plugin in `cursor/plugins`; `LICENSE` beside it) |
|
|
21
21
|
|
|
22
22
|
The owning skill above is where each contract is defined; a role prompt that needs a contract from its own seat points there or restates only its own step. This file lists and does not restate.
|
|
23
|
-
|
|
24
|
-
A
|
|
23
|
+
The skills here ship in two Oh My Pi plugins, and the partition is kept in one place, `scripts/pi-plugin-prepack.sh` at the repository root, keyed by package name: `@sjawhar/pi-envoy` (`packages/pi-envoy`) ships `dispatch`, `dispatch-first`, `dispatch-brainstorming` and `envoy`, the skills every session with Dispatch reads; `@sjawhar/pi-legion` (`packages/pi-legion`) ships `legion-architect`, `legion-controller`, `legion-oracle`, `legion-retro`, `legion-worker`, `ce-simplify-code`, `thermonuclear-code-quality` and `thermonuclear-deep-review`, the skills a Legion pane's prompts load. Each plugin's prepack stages its list into its `dist/skills`, and `packages/pi-shared/test/skills-partition.test.ts` holds the two lists to this directory: together they are every skill directory here, and none is in both. A link from a skill in one partition into a skill in the other (a Legion skill's link into `dispatch`) is written `skill://<name>/<path>`, never as a relative path: a staged partition is installed on its own, so a relative link out of it dangles, while a `skill://` link resolves by name once both plugins are installed.
|
|
24
|
+
A Legion prompt (a skill here, a role prompt, or an agent definition in `packages/pi-legion/agents/`) names a task agent only as `task(agent="<name>")` and a skill it tells the model to load only as `skill://<name>`. Those are the two forms the Go daemon's boot gate and `legion probe-image` resolve through Oh My Pi, refusing by name one it cannot find; a dispatch or a load written any other way goes unchecked. An agent or skill Legion's prompts name is shipped here or in `packages/pi-legion/agents/`, unless Oh My Pi bundles it.
|
|
25
|
+
A skill file an agent loads stays under 51,200 bytes, Oh My Pi's spill threshold (a longer one arrives with its middle cut out), and a skill's detail lives in `references/` files linked as `skill://<name>/references/<file>.md`, never by relative path, which a read by path cuts at 300 lines. The rules are `packages/pi-shared/test/skills-guard.ts`, run over each plugin's staged partition: `packages/pi-envoy/src/skills-guard.test.ts` over the Envoy plugin's four skills, with the `dispatch-first` budget check, and `packages/pi-legion/src/skills-guard.test.ts` over the Legion plugin's eight, with the daemon's prompts as linking roots and every `legion-worker` reference linked from somewhere. Each fails on a file at the threshold, on any `SKILL.md` body of 500 lines or more, on a skill whose frontmatter `name` is not its directory's name, on a `skill://<name>/<path>` link that names a missing file or a missing `#heading` (resolved against this directory, where both partitions live), and on a relative link that leaves the staged partition or names no file. The Envoy guard also fails on a `task(agent="<name>")` in the Envoy plugin's skills that names an agent neither that plugin nor Oh My Pi bundles (the bundled list read off the pinned binary's `omp agents unpack` under `LEGION_TEST_OMP`, never written down), since those skills reach a session with no other plugin installed; a `skill://legion-*` mention there is a sentence conditioned on a Legion role, inert for a person and right for a pane with both plugins, which the guard leaves alone.
|
|
25
26
|
The text a worker boots with (its role prompt) lives in `packages/daemon/internal/prompts/roles/`,
|
|
26
27
|
embedded in the `legion` binary and composed per role by `packages/daemon/internal/prompts/prompts.go`;
|
|
27
28
|
`packages/daemon/internal/prompts/roles_test.go` holds the structural rules for those parts.
|
|
@@ -50,7 +50,7 @@ found yourself.
|
|
|
50
50
|
A design conversation with a person, or the implementation plan that follows one, uses
|
|
51
51
|
`skill://dispatch-brainstorming`: read it before your first design question on a change, the spec,
|
|
52
52
|
or that plan. It replaces superpowers' `brainstorming` and `writing-plans` here, even when the user
|
|
53
|
-
invokes one by name.
|
|
53
|
+
invokes one by name. Before a spec's first version and each approval request, have a fresh read-only subagent (on Oh My Pi, `task(agent="scout")`, or whatever read-only agent the host bundles) check it against the code, the human's words and any command output a claim rests on, and resolve what it flags. A Legion architect's own issue spec follows `skill://legion-architect`, and its fresh reader in that Legion session is the Legion plugin's `plan-gap-analyst` agent.
|
|
54
54
|
|
|
55
55
|
## Load the full skill before you write
|
|
56
56
|
|
|
@@ -77,14 +77,14 @@ exercise a criterion end to end, building that path is a child issue of this tre
|
|
|
77
77
|
answers the tree's asks); under a personal token it goes to that token's owner, whom
|
|
78
78
|
`dispatch_whoami` names. Set it only when a human told you a specific person owns that child.
|
|
79
79
|
|
|
80
|
-
Specifications written into Dispatch follow `skill://dispatch`'s
|
|
80
|
+
Specifications written into Dispatch follow `skill://dispatch`'s [Writing a spec](skill://dispatch/SKILL.md#writing-a-spec).
|
|
81
81
|
Wave releases, child closures, and your own status are visible from the issue tree and the
|
|
82
82
|
handoffs; do not narrate them into the spec or a `dispatch_message`. A to-do only a human can
|
|
83
83
|
clear is a `dispatch_ask`.
|
|
84
84
|
|
|
85
85
|
The issue's primary document **is** the root specification. Extend it in place: a new version
|
|
86
86
|
that adds only the evidence each decision needs and what the human decides, each as a
|
|
87
|
-
decision block
|
|
87
|
+
[decision block](skill://dispatch/SKILL.md#decision-blocks). The decomposition and its waves, how each
|
|
88
88
|
outcome is proven, and the integration test are your own calls: they go in the child issues and
|
|
89
89
|
the planner's `.legion/<issue>/plan.json`, not the root spec. Never post a second "spec" artifact beside
|
|
90
90
|
it (`dispatch_artifact` with the primary document's name replaces the human's document; do not do
|
|
@@ -112,7 +112,7 @@ legion({
|
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
The decision blocks come first: settle every one as
|
|
115
|
-
|
|
115
|
+
[Approval of a spec](skill://dispatch/SKILL.md#approval-of-a-spec) says before you request approval;
|
|
116
116
|
`dispatch_request_approval` refuses while one is open. Each answer reaches you, since you follow
|
|
117
117
|
every ask you open. An approval request carries nothing new: request it only once the human has
|
|
118
118
|
agreed to every point in the spec, so a point they have not agreed to gets its own decision block
|
|
@@ -26,8 +26,8 @@ For an interactive takeover from a hand-started OMP session, start OMP with
|
|
|
26
26
|
`LEGION_DAEMON_URL`, `LEGION_PROJECT` (the daemon's project), `LEGION_STATE_DIR`, and `LEGION_GRANT_FILE`
|
|
27
27
|
(an absolute path to a file only you can read, under a 0700 directory; the extension writes
|
|
28
28
|
each command's grant there and every `bash` call is blocked without it) in its environment. Do
|
|
29
|
-
not set `LEGION_CONTROLLER=1` — that marker is
|
|
30
|
-
carrying it claims at startup. Then run:
|
|
29
|
+
not set `LEGION_CONTROLLER=1` — that marker is the launched controller's own (`legion controller
|
|
30
|
+
start`'s session, or the daemon's pod), and a session carrying it claims at startup. Then run:
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
33
|
/legion-claim-controller
|
|
@@ -50,12 +50,27 @@ retry. And the role does not follow `/new` or `/fork` in a takeover session —
|
|
|
50
50
|
`LEGION_CONTROLLER=1` the new session is not a Legion session to the extension — so after either
|
|
51
51
|
command run `/legion-claim-controller` again.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
Daemon state and the Dispatch project remain authoritative, and the start procedure below reads
|
|
54
|
+
what happened while no controller ran. Who launched you is the deployment's `controller` setting:
|
|
55
|
+
the operator, or the daemon itself. The `How this controller runs` part of your system prompt says
|
|
56
|
+
which.
|
|
57
|
+
|
|
58
|
+
### Started by the daemon
|
|
59
|
+
|
|
60
|
+
Under `controller: daemon` the daemon launched you as a pod in the cluster and supervises you like
|
|
61
|
+
a root architect: you run headless (`omp --mode rpc`), nobody types into your session, and nobody
|
|
62
|
+
reads your replies as they appear. The extension registered with your launch's boot token, claimed
|
|
63
|
+
the role, subscribed to the controller topic and reported ready; the daemon then sent your start
|
|
64
|
+
message. When your pod dies the daemon relaunches it and resumes this same session, with a new
|
|
65
|
+
start message, so run the start procedure each time one arrives. A human reaches you through
|
|
66
|
+
Dispatch (a message to your session on the Agents page, a reply to an ask you opened, a mention) or
|
|
67
|
+
Envoy: answer them where they will read it, a Dispatch message or reply, since text left only in
|
|
68
|
+
your session reaches no one. `legion state` and `legion status <KEY> <status>` work as below. There
|
|
69
|
+
is no `legion controller start` against this daemon, and nobody can replace you with one.
|
|
55
70
|
|
|
56
71
|
### Started by the operator
|
|
57
72
|
|
|
58
|
-
|
|
73
|
+
Under `controller: operator`, the default, the daemon launches no controller: the operator ran
|
|
59
74
|
`legion controller start --config controller.yaml [--daemon-url <url>]` on
|
|
60
75
|
their own machine, and you are that foreground OMP session. The command fetched a fresh controller
|
|
61
76
|
secret from the daemon with the operator's token, wrote it to a 0600 file under `LEGION_STATE_DIR`
|
|
@@ -78,8 +93,10 @@ mints a new secret, so your grants stop working and the role moves to the new se
|
|
|
78
93
|
The Go daemon's controller topic is a wake for a session that is running when it is published.
|
|
79
94
|
Envoy hands an Oh My Pi session no retained copy of a notice published before it subscribed, so a
|
|
80
95
|
hold, a tree architect's failed claim, a new triage root, or a freed slot from while no controller
|
|
81
|
-
ran never arrives as a wake.
|
|
82
|
-
(`Legion controller start: …`)
|
|
96
|
+
ran never arrives as a wake. Every launch opens your first turn with a start message
|
|
97
|
+
(`Legion controller start: …`) — `legion controller start` passes it, and the daemon sends it to a
|
|
98
|
+
controller it launched once that controller is ready — so every start and restart runs this
|
|
99
|
+
procedure with nothing typed.
|
|
83
100
|
At every start, after the claim recheck ([Turn discipline](#turn-discipline)) and before anything
|
|
84
101
|
else:
|
|
85
102
|
|
|
@@ -350,7 +367,7 @@ priority first, then board rank ([Keeping the slots full](#keeping-the-slots-ful
|
|
|
350
367
|
`unassigned`, `Unassigned — nobody's Inbox shows this tree's questions or its design approval
|
|
351
368
|
until someone takes it from the issue header (Assignee, beside Priority)`. The design approval
|
|
352
369
|
is promised only when the `Design gate policy:` line of your system prompt, which
|
|
353
|
-
|
|
370
|
+
whoever launched you writes from the daemon's own configuration, says
|
|
354
371
|
`gates.design: root-issues`. Under `gates.design: off` nobody approves a design, so drop "and
|
|
355
372
|
its design approval" (and "or its design approval") from the sentence. An unassigned root
|
|
356
373
|
still runs; the architect's asks wait in every Inbox's Unassigned band.
|
|
@@ -167,7 +167,7 @@ other tree paused.
|
|
|
167
167
|
|
|
168
168
|
## Phase work
|
|
169
169
|
|
|
170
|
-
Specifications written into Dispatch follow `skill://dispatch`'s
|
|
170
|
+
Specifications written into Dispatch follow `skill://dispatch`'s [Writing a spec](skill://dispatch/SKILL.md#writing-a-spec), except that a phase worker writes no decision block: it sends an open product, scope or design decision to its architect, which writes the block.
|
|
171
171
|
|
|
172
172
|
Follow the repository's normal engineering workflow and the assigned issue's acceptance
|
|
173
173
|
criteria. Your phase's own charter and the predecessor handoffs you read define the phase
|