@sjawhar/opencode-legion-envoy 1.21.0 → 1.22.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
|
@@ -16031,10 +16031,16 @@ class EnvoyApiError extends Error {
|
|
|
16031
16031
|
this.expected = parsed?.expected;
|
|
16032
16032
|
}
|
|
16033
16033
|
}
|
|
16034
|
+
function resolveEnvoyToken(env) {
|
|
16035
|
+
const { ENVOY_TOKEN_FILE: file, ENVOY_TOKEN: plain } = env;
|
|
16036
|
+
if (file !== undefined && file !== "")
|
|
16037
|
+
return readSecretFile("ENVOY_TOKEN_FILE", file);
|
|
16038
|
+
return plain || undefined;
|
|
16039
|
+
}
|
|
16034
16040
|
function createEnvoyClient(config) {
|
|
16035
16041
|
const baseUrl = normalizeEnvoyUrl(config.baseUrl);
|
|
16036
16042
|
const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
16037
|
-
const
|
|
16043
|
+
const apiToken = resolveEnvoyToken(process.env);
|
|
16038
16044
|
const request = async (path, init) => {
|
|
16039
16045
|
const url = `${baseUrl}${path}`;
|
|
16040
16046
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
package/package.json
CHANGED
package/skills/envoy/SKILL.md
CHANGED
|
@@ -148,11 +148,16 @@ not construct a token from a partial issue reference.
|
|
|
148
148
|
|
|
149
149
|
## Legion exception lane
|
|
150
150
|
|
|
151
|
-
`no_holder` and `
|
|
152
|
-
add a second subscriber or manually retry.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
`no_holder`, `delivery_failed`, and `receipt_timeout` for a Legion role are daemon liveness
|
|
152
|
+
signals, not reasons to add a second subscriber or manually retry. `no_holder`: no live session
|
|
153
|
+
holds the role. `delivery_failed`: the message was not forwarded at all — the holder lookup
|
|
154
|
+
failed, the holder was stale, or the publish errored. `receipt_timeout`: the listener forwarded
|
|
155
|
+
the message to a registered, live holder and no receipt arrived inside the window; its payload
|
|
156
|
+
keeps `original_topic`, `event_id`, `payload`, and the original `dedupe_key`, so the daemon can
|
|
157
|
+
re-send the same message and the receiver's dedupe drops a copy that did arrive. Treat any of
|
|
158
|
+
these wakes as the daemon's responsibility to revive or recreate the backing worker and
|
|
159
|
+
re-deliver; otherwise it resurrects the root process with derived catch-up and the workspace
|
|
160
|
+
handoffs. Raw delivery failures stay out of architect context.
|
|
156
161
|
|
|
157
162
|
## Slack
|
|
158
163
|
|
|
@@ -285,7 +285,11 @@ entire end-game sequence has completed.
|
|
|
285
285
|
## Wake routing
|
|
286
286
|
|
|
287
287
|
Handle one delivered wake by verifying the relevant live artifact and then performing the
|
|
288
|
-
corresponding lifecycle procedure.
|
|
288
|
+
corresponding lifecycle procedure. Architect-addressed wakes always reach the architect that owns
|
|
289
|
+
the payload issue: a claimed child sub-architect, otherwise the nearest claimed ancestor, then the
|
|
290
|
+
root. A wake about an architect role's own launch reaches the architect above it. `phase-complete`,
|
|
291
|
+
worker lifecycle, child lifecycle, and design-gate wakes are architect-only and never go to an
|
|
292
|
+
active phase worker.
|
|
289
293
|
|
|
290
294
|
| Wake | Procedure |
|
|
291
295
|
| --- | --- |
|
|
@@ -305,8 +309,8 @@ corresponding lifecycle procedure.
|
|
|
305
309
|
| `pr-merged` | Payload `{type:"pr-merged", pr, mergeCommitSha}`. The merge queue landed the PR. `spawn_worker` the **implementer** with the production-check task naming that merge commit (it resumes the same agent; a retired role has no live holder, so never `envoy_publish` for this). Its `phase-complete` is what brings you to step 7: verify the record on the pull request and this issue first, then sign off naming it and set the issue `done`. A merge is not the close. |
|
|
306
310
|
| `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. |
|
|
307
311
|
| `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. |
|
|
308
|
-
| `catchup-overseer` | Verify its
|
|
309
|
-
| `worker-died` | Payload `{type:"worker-died", issue, role}`.
|
|
312
|
+
| `catchup-overseer` | Verify its child counts and PR verdicts against current artifacts, then resume the applicable lifecycle step. This is a current-state snapshot, not a raw-event replay. A root architect uses `gates[LEGION_TREE].open`: `true` means the root spec is approved and section 2 may continue; `false`, or no `open` key, means section 1 still applies. A resumed sub-architect receives `overseerCatchup(state, LEGION_ISSUE)` for its own subtree: its `gates` intentionally omits the root gate because a child spec is never gated. Do not request or register a gate; resume at section 2. Handle each `phaseCompletions` entry exactly as a `phase-complete` wake, then compare `childCounts[LEGION_ISSUE].open` with `legion state` and Dispatch before deciding the next action. |
|
|
313
|
+
| `worker-died` | Payload `{type:"worker-died", issue, role}`. Two causes, one verdict: the daemon retried this role's boot through `MAX_LAUNCH_FAILURES` attempts and could not confirm it, or the worker booted and acknowledged every prompt without ever starting a turn through `MAX_PROMPT_RETIRES` retire-and-relaunch cycles (LEGION-93) — never a raw-event replay or a silent revive. Your next `spawn_worker` for the role is the retry (one cold launch, three prompts, and `worker-died` again if the agent is still broken). Reassess the work and `spawn_worker` again for the role (it resumes the same agent via `--resume` if a session file survived) or reassign it if the failure looks environmental, not agent-specific. |
|
|
310
314
|
| `reopened` | Reopen the root lifecycle: inspect the reason and current artifacts, reassess scope and children, and resume at the first applicable numbered step. |
|
|
311
315
|
|
|
312
316
|
## Escalation judgment
|
|
@@ -62,7 +62,8 @@ override a Sami ruling quoted here.
|
|
|
62
62
|
| New issue created in the Dispatch project (`issue.created`, status `triage`; resync heals misses) | issue key + triage context (incl. pre-existing children) | Triage: `legion({ op: "set_status", issue, status: "todo" })` to admit, or set `backlog`/`icebox` to park |
|
|
63
63
|
| Backlog eligibility | slot freed / priority change | Reconsider parked items and move the eligible root to `todo` |
|
|
64
64
|
| Architect escalation (controller-actionable only: re-file a child as a root issue, capacity, cross-tree conflicts) | request + context | Judge and act; issue-scoped human Q&A goes through `dispatch_ask` from the owning architect, not here |
|
|
65
|
-
| Resync report | artifact-driven anomaly list (zero-owner trees, untriaged-open, launch-failed) | Verify against fresh state, then heal |
|
|
65
|
+
| Resync report | artifact-driven anomaly list (zero-owner trees, untriaged-open, launch-failed, admission-drift) | Verify against fresh state, then heal |
|
|
66
|
+
| Resync report: `admission-drift` entry | issue key + whether the daemon added it to, or removed it from, its admission list (the detail says which) | No action: the daemon already repaired it in the same run. An issue that reappears in consecutive reports is a live leak — file a LEGION issue on Dispatch with both reports pasted as evidence (never a GitHub issue) |
|
|
66
67
|
| `child-status` | child key + status transition | Not controller-actionable by default; if the daemon could not route it to the parent's architect role, verify the transition and forward it with `envoy_publish` |
|
|
67
68
|
| Mention | Slack/GitHub PR @mention text | Answer, or route to the owning issue's architect role |
|
|
68
69
|
| Closed-tree activity (comment, review, CI on a closed tree) | issue, root, event summary | Read the artifact; if work should resume, `legion({ op: "set_status", issue: root, status: "todo" })`; otherwise no action — the event is not held or redelivered |
|
|
@@ -124,7 +125,10 @@ Treat a resync report as an anomaly list, not an instruction. For every zero-own
|
|
|
124
125
|
untriaged-open, or launch-failed issue it names, verify `legion state --json` and the
|
|
125
126
|
current Dispatch issue first. Then heal the verified condition: admit an eligible root, move
|
|
126
127
|
an issue back to its intended status, or use the applicable daemon control path. Do not act
|
|
127
|
-
on stale entries until their source artifact explains the anomaly.
|
|
128
|
+
on stale entries until their source artifact explains the anomaly. An `admission-drift` entry
|
|
129
|
+
needs no healing — the daemon added the tree back to (or removed it from) its admission list in
|
|
130
|
+
the same run; verify only that the same issue does not recur in the next report, and file a
|
|
131
|
+
LEGION issue with both reports if it does.
|
|
128
132
|
|
|
129
133
|
## Mentions
|
|
130
134
|
|
|
@@ -22,13 +22,14 @@ completes the boot handshake for you at session start — it registers with the
|
|
|
22
22
|
your role, and signals readiness. You never call `envoy_role_set` yourself.
|
|
23
23
|
|
|
24
24
|
Your role token is not the issue key spelled out literally. The daemon encodes it as
|
|
25
|
-
`legion-<project>-<KEY>-<role>`. For example, project `acme`, issue `LEGION-41`, role
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
been given before recomputing
|
|
25
|
+
`legion-<project>-<KEY>-<role>`. For example, project `acme`, issue `LEGION-41`, role `architect`
|
|
26
|
+
encodes to `legion-acme-LEGION-41-architect`. Never hand-format one for another role: your own role
|
|
27
|
+
topic and the topic of the architect that owns your issue are stated at the end of your system
|
|
28
|
+
prompt (a "Legion addressing" line the daemon appends: on a child issue that is the child's
|
|
29
|
+
sub-architect when one is claimed, else the root's), a sibling role's topic is yours with the
|
|
30
|
+
trailing `-<role>` replaced, and the `roleToken` helper in `@legion/contracts` computes any other
|
|
31
|
+
one exactly the way the daemon does — prefer a topic you've already been given before recomputing
|
|
32
|
+
one.
|
|
32
33
|
|
|
33
34
|
If the handshake fails (a rejected boot token, or a bootstrap failure after your role
|
|
34
35
|
registered), the extension logs it and exits the process outright — it does not retry, and
|