@sjawhar/opencode-legion-envoy 0.12.2 → 0.13.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.
@@ -13881,7 +13881,7 @@ var DISPATCH_URGENCIES = ["low", "med", "high", "blocking"];
13881
13881
  var DISPATCH_TOOL_DESCRIPTION = "Raise a durable question to the human as a Dispatch thread (a GitHub issue shown on the dashboard), or continue an existing thread with a follow-up question. The reader has NOT seen your transcript. Open a thread with `subject`; continue one with `thread`. The reply arrives in this session as a steer.";
13882
13882
  var DISPATCH_ARGUMENTS = {
13883
13883
  subject: "Open a new thread: one line naming the decision needed (the issue title). Omit when continuing a thread with `thread`.",
13884
- thread: `Continue an existing thread: "<n>" (an issue in the working directory's repo) or "owner/name#<n>". When set, omit subject, urgency, repo, and parent.`,
13884
+ thread: 'Continue an existing thread: "<n>" (an open issue in the repo; a plain work issue is adopted as a thread) or "owner/name#<n>". When set, omit subject, urgency, repo, and parent.',
13885
13885
  context: `What you are doing, what you found, why you are stuck \u2014 at most ${DISPATCH_CONTEXT_MAX} characters, at most three short paragraphs or a bullet list. The reader has NOT seen your transcript: no nouns you coined this session, no internal identifiers unless the question is about them. GitHub references (#N, owner/repo#N, URLs) may be bare; the dashboard unfurls them.`,
13886
13886
  question: `The ask, at most ${DISPATCH_QUESTION_MAX} characters, as a list: current state \u2192 desired state \u2192 your recommendation and why; options go in \`ask\`.`,
13887
13887
  ask: "Structured questions rendered as buttons on the dashboard. Each: { question, header?, options: [{ label, description? }], multiple?, custom? }. Use this whenever the answer is one of N choices.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -154,7 +154,8 @@ dispatch({
154
154
  ```
155
155
 
156
156
  - `thread` replaces `subject`; `urgency`, `repo`, and `parent` are not accepted with it.
157
- The thread must be open and be a dispatch thread; otherwise the tool says so
157
+ `thread` names an open issue in the repo; a plain work issue is adopted as a thread on
158
+ first use. The issue must be open and not a pull request, or the tool says so
158
159
  (`#N is not a dispatch thread`, `#N is closed; open a new thread`).
159
160
  - Same decision → same thread. A genuinely new decision → a new thread, even if it came
160
161
  up in the reply.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: legion-controller
3
- description: Use when handling Legion controller wakes for root-issue triage, backlog admission, architect escalation, resync healing, human interaction, or gate approval.
3
+ description: Use when handling Legion controller wakes for root-issue triage, backlog admission, architect escalation, resync healing, or human interaction.
4
4
  ---
5
5
 
6
6
  # Legion Controller
@@ -23,8 +23,8 @@ For an interactive takeover, start OMP with `LEGION_CONTROLLER_SECRET` and
23
23
 
24
24
  The command resolves the project from daemon state, claims the Envoy role for the current
25
25
  session, and posts readiness before controller commands can act. It retains the environment
26
- capability for `legion admit`, `legion approve`, and `legion backlog`. Never pass a secret as a
27
- command argument or copy it into a transcript.
26
+ capability for `legion admit` and `legion backlog`. Never pass a secret as a command argument
27
+ or copy it into a transcript.
28
28
 
29
29
  This handshake lets the daemon redeliver held controller work. It does not turn the controller
30
30
  into a state holder: daemon state and GitHub artifacts remain authoritative.
@@ -49,7 +49,7 @@ into a state holder: daemon state and GitHub artifacts remain authoritative.
49
49
  | 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` from the owning architect, not here |
50
50
  | Resync report | artifact-driven anomaly list (zero-owner trees, erroring issues) | Verify against fresh state, then dispatch/heal |
51
51
  | Mention | Slack/GitHub @mention text | Answer, or route to the owning issue's architect role |
52
- | Approval interpretation | ambiguous human comment on a gated issue | Decide whether it's an approval; if so, apply `human-approved` via the daemon |
52
+ | Closed-tree activity (comment, review, CI on a closed tree) | issue, root, event summary | Read the artifact; if work should resume, `legion admit <root>`; otherwise no action — the event is not held or redelivered |
53
53
  | Direct user message | — | Always first |
54
54
 
55
55
  ## New issue triage
@@ -111,19 +111,6 @@ human-facing information. Otherwise resolve the authoritative owning architect r
111
111
  route the verified context with `envoy_publish`. Do not route raw event traffic or invent a
112
112
  role token from a partial issue reference.
113
113
 
114
- ## Approval interpretation
115
-
116
- For an ambiguous human comment on a gated issue, verify the current issue, gate state, and
117
- comment's meaning. If it is Sami's approval, apply the daemon transition:
118
-
119
- ```bash
120
- legion approve <issue>
121
- ```
122
-
123
- This applies `human-approved` and clears `needs-approval` atomically. It is not a generic
124
- label-edit operation. The design gate remains skill-enforced by the architect, and the
125
- merge gate remains config-armed until Sami approves the final reviewed head.
126
-
127
114
  ## Label vocabulary
128
115
 
129
116
  Use only the project labels below, with their stated ownership:
@@ -1,47 +1,88 @@
1
1
  ---
2
2
  name: legion-worker
3
- description: Use when dispatched as an architect, plan, implement, test, or review phase worker in a Legion issue workspace.
3
+ description: Use when dispatched as a per-process Legion phase worker — architect (on a child issue), planner, implementer, tester, reviewer, or merger booted from the daemon's LEGION_* environment.
4
4
  ---
5
5
 
6
6
  # Legion Phase Worker
7
7
 
8
- You are one phase in a shared issue workspace, not a dispatcher or pipeline coordinator. The
9
- architect owns the tree; phases use the same jj workspace sequentially. Complete the phase
10
- assigned in the prompt, return its structured output to the architect, and leave the durable
11
- copy that the next phase can trust.
8
+ You are one phase in a shared issue workspace, running as your own OMP process — not a
9
+ `task`-spawned subagent and not a pipeline coordinator. The architect owns the tree; each
10
+ phase gets its own long-lived process against the same jj workspace, run in turn. Complete
11
+ the phase assigned to you, report its completion to the architect, and leave the durable
12
+ copy the next phase can trust.
12
13
 
13
14
  ## Identity, scope, and role
14
15
 
15
- The dispatch supplies the issue, phase, daemon-minted role token, workspace, and task
16
- `outputSchema`. At startup, claim that role with `envoy_role_set`; never construct a role
17
- token from an issue name. A claim survives parking, and a revived or re-created worker claims
18
- its own role again.
19
-
20
- Read the current issue and its acceptance criteria before changing the workspace. Work only
21
- on this phase's artifact. You may use ordinary scouts, reviewers, and oracle subagents for
22
- phase work; never spawn legion-role workers. Escalate a product, scope, cross-phase, or
23
- lifecycle decision to the owning architect through hub, with the verified facts and the
24
- decision needed. For a durable question that needs Sami directly, you may use the raw
25
- `dispatch` MCP tool yourself; replies return to your own session.
16
+ The daemon spawns you as a separate `omp --mode rpc` process (behind `legion worker-shim`,
17
+ in a tmux pane) with `LEGION_TREE`, `LEGION_ISSUE`, `LEGION_ROLE`, `LEGION_GENERATION`,
18
+ `LEGION_BOOT_TOKEN`, `LEGION_DAEMON_URL`, `LEGION_STATE_DIR`, and `LEGION_WORKSPACE` in your
19
+ environment (`LEGION_PROJECT` is also supplied, but nothing reads it). The extension
20
+ completes the boot handshake for you at session start — it registers with the daemon, claims
21
+ your role, and signals readiness. You never call `envoy_role_set` yourself.
22
+
23
+ Your role token is not the issue key spelled out literally. The daemon encodes it as
24
+ `legion-<project>-<encoded-owner>__<encoded-repo>-<number>-<role>`, escaping `_`, `.`, and
25
+ `-` within the owner and repo names (`_u`, `_d`, `_h`) so `__` is always the one safe
26
+ separator. For example, project `acme`, issue `sjawhar/legion#41`, role `architect` encodes
27
+ to `legion-acme-sjawhar__legion-41-architect`. Never hand-format one for another role: the
28
+ daemon's boot response already gives you your own token, and the `roleToken` helper in
29
+ `@legion/contracts` computes any other one exactly the way the daemon does — reuse a token
30
+ you've already been given before recomputing it.
31
+
32
+ If the handshake fails (a rejected boot token, or a bootstrap failure after your role
33
+ registered), the extension logs it and exits the process outright — it does not retry, and
34
+ you do not troubleshoot it by hand. The daemon resumes this same session from its recorded
35
+ session file the next time this role is needed; that is not an instant automatic respawn.
36
+
37
+ Once ready, your assignment arrives as the first prompt in your session — you do not fetch
38
+ it. Read the current issue and its acceptance criteria before changing the workspace. Work
39
+ only on this phase's artifact.
40
+
41
+ You never spawn another Legion role: spawning a worker
42
+ (`legion({op: "spawn_worker", ... })`) is architect-only. You may still use ordinary `task`
43
+ scouts, reviewers, and oracle subagents for your own phase work; they are not Legion roles.
44
+ Escalate a product, scope, cross-phase, or lifecycle decision to the owning architect with
45
+ `envoy_publish` to its role topic (`notifications.role.` followed by its encoded token, see
46
+ above), carrying the verified facts and the decision needed. `hub` only reaches subagents
47
+ inside your own process, not the architect's separate one. For a durable question that needs
48
+ Sami directly, you may use the raw `dispatch` MCP tool yourself; replies return to your own
49
+ session.
50
+
51
+ Because the same agent is always resumed for its phase, you may receive more than one
52
+ assignment across your lifetime: after you complete and go idle, a later event (a review
53
+ round, a question) can deliver a new prompt to this same session. Treat it as a
54
+ continuation — re-read the current issue and your own prior handoff, since time has
55
+ passed — never as a fresh identity.
56
+
57
+ ## Asking another role
58
+
59
+ Reach any live role on this issue the same way you reach the architect: `envoy_publish` to
60
+ `notifications.role.` followed by that role's encoded token. Use it when you need context an
61
+ earlier phase has that its handoff doesn't cover — ask the planner why a constraint was
62
+ scoped that way, ask the implementer what a commit actually did. A role that finished its
63
+ phase is still alive and idle in its pane; it answers.
26
64
 
27
65
  ## Workspace and handoff precedence
28
66
 
29
- The `workspace` attribute in your `<legion-spawn>` block is the authoritative issue
30
- workspace. Before reading repository files or handoffs, you **MUST** bind to that exact
31
- path with:
67
+ `LEGION_WORKSPACE` is the authoritative issue workspace. Before reading repository files or
68
+ handoffs, you **MUST** bind to that exact path with:
32
69
 
33
70
  ```bash
34
- cd -- "<workspace>" && jj -R "<workspace>" status
71
+ cd -- "$LEGION_WORKSPACE" && jj -R "$LEGION_WORKSPACE" status
35
72
  ```
36
73
 
37
74
  Never rely on the inherited cwd. Every later repository shell command **MUST** begin
38
- `cd -- "<workspace>" &&`; every jj command **MUST** use `-R "<workspace>"`; and native
39
- filesystem tool paths **MUST** be absolute under that workspace. Do not create an isolated
40
- worktree, change the workspace topology, or mix another issue's work into it. Concurrent
41
- issues have disjoint workspaces; phases for this issue are sequential.
75
+ `cd -- "$LEGION_WORKSPACE" &&`; every jj command **MUST** use `-R "$LEGION_WORKSPACE"`; and
76
+ native filesystem tool paths **MUST** be absolute under that workspace. Do not create an
77
+ isolated worktree, change the workspace topology, or mix another issue's work into it.
78
+ Concurrent issues have disjoint workspaces; only the currently active phase mutates this
79
+ one. After you complete and go idle, treat `$LEGION_WORKSPACE` as read-only: you are kept
80
+ alive to answer questions, not to keep editing. Do not create new commits, run
81
+ `jj -R "$LEGION_WORKSPACE" new`, or touch tracked files once your own handoff is committed
82
+ and pushed — a code change belongs to whichever phase is active now.
42
83
 
43
84
  On every start, and especially after revival or re-creation, read the issue and then the
44
- committed predecessor handoffs in lifecycle order from `<workspace>/.legion/`:
85
+ committed predecessor handoffs in lifecycle order from `$LEGION_WORKSPACE/.legion/`:
45
86
 
46
87
  1. `architect.json`
47
88
  2. `plan.json`
@@ -49,39 +90,42 @@ committed predecessor handoffs in lifecycle order from `<workspace>/.legion/`:
49
90
  4. `test.json`
50
91
  5. `review.json`
51
92
 
52
- Read only files that precede the assigned phase. The live path returns JSON matching the task
53
- `outputSchema` directly to the architect. The durable path uses the **same schema** in
54
- `<workspace>/.legion/<phase>.json`. If a committed handoff conflicts with memory or a prior
55
- transcript, the committed file wins: it is the copy that survived.
93
+ Read only files that precede the assigned phase. There is no handoff schema (rejected
94
+ design no schema validation runs anywhere in this pipeline): write the phase-specific
95
+ fields the next phase and the architect need, consistent with what predecessor phases
96
+ already wrote. The durable copy lives in `$LEGION_WORKSPACE/.legion/<phase>.json`. If a
97
+ committed handoff conflicts with memory or a prior transcript, the committed file wins: it
98
+ is the copy that survived.
56
99
 
57
100
  ## jj Safety Rules
58
101
 
59
- - **Always `jj -R "<workspace>" new` to create isolated commits.** Never
60
- `jj -R "<workspace>" edit @-` to go back to a parent — this changes what `@` points to
61
- and makes `jj abandon` dangerous.
62
- - **Never `jj -R "<workspace>" abandon`.** If a mistake would require abandoning work,
63
- stop and send the owning architect the `jj -R "<workspace>" log` evidence.
64
- - **Before pushing, check ancestry:** `jj -R "<workspace>" log -r 'ancestors(@, 5)'`
65
- verify only your issue's commits are in the chain, not unrelated work.
102
+ - **Always `jj -R "$LEGION_WORKSPACE" new` to create isolated commits.** Never
103
+ `jj -R "$LEGION_WORKSPACE" edit @-` to go back to a parent — this changes what `@` points
104
+ to and makes `jj abandon` dangerous.
105
+ - **Never `jj -R "$LEGION_WORKSPACE" abandon`.** If a mistake would require abandoning
106
+ work, stop and send the owning architect the `jj -R "$LEGION_WORKSPACE" log` evidence.
107
+ - **Before pushing, check ancestry:** `jj -R "$LEGION_WORKSPACE" log -r 'ancestors(@, 5)'`
108
+ verify only your issue's commits are in the chain, not unrelated work.
66
109
 
67
- **Shared operation safety:** Never run `jj op restore` in a Legion workspace. It rewrites the
68
- shared operation log. If a mistake reaches that point, stop and send the owning architect the
69
- `jj -R "<workspace>" log` evidence; recover only through the approved, path-scoped workflow.
110
+ **Shared operation safety:** Never run `jj op restore` in a Legion workspace. It rewrites
111
+ the shared operation log. If a mistake reaches that point, stop and send the owning
112
+ architect the `jj -R "$LEGION_WORKSPACE" log` evidence; recover only through the approved,
113
+ path-scoped workflow.
70
114
 
71
115
  ## Phase work
72
116
 
73
- Follow the repository's normal engineering workflow and the assigned issue's acceptance criteria.
74
- The dispatch output schema defines the phase artifact and completion evidence. Do not replace
75
- architect-owned decomposition, gate discipline, scheduling, or human communication with labels
76
- or a local status model.
117
+ Follow the repository's normal engineering workflow and the assigned issue's acceptance
118
+ criteria. Your phase's own charter and the predecessor handoffs you read define the phase
119
+ artifact and its completion evidence. Do not replace architect-owned decomposition, gate
120
+ discipline, scheduling, or human communication with labels or a local status model.
77
121
 
78
- Commit attribution is automatic: the Legion extension exports a `JJ_CONFIG` overlay at root
79
- bootstrap, so every jj commit made in the session family carries an `Omp-Session: <root-session-id>`
122
+ Commit attribution is automatic: the extension exports a `JJ_CONFIG` overlay when your
123
+ session starts, so every jj commit you make carries an `Omp-Session: <this-session-id>`
80
124
  trailer with no action from you. Do not add attribution trailers by hand.
81
125
 
82
- The jj configuration already supplies the phase worker's plus-addressed author and committer
83
- identity. Do not override Git identity configuration. The worker session receives the
84
- credential capability it needs; invoke GitHub through the credential helper:
126
+ The jj configuration already supplies your phase's plus-addressed author and committer
127
+ identity. Do not override Git identity configuration. Your session receives the credential
128
+ capability it needs; invoke GitHub through the credential helper:
85
129
 
86
130
  ```bash
87
131
  legion gh -- <gh args…>
@@ -89,9 +133,9 @@ legion gh -- <gh args…>
89
133
 
90
134
  ## GitHub comment attribution
91
135
 
92
- Append this exact structured footer to **every** GitHub issue comment, pull-request comment,
93
- and review that this phase posts. It preserves session provenance on the artifact itself so
94
- work stays attributable to the session that produced it:
136
+ Append this exact structured footer to **every** GitHub issue comment, pull-request
137
+ comment, and review that this phase posts. It preserves session provenance on the artifact
138
+ itself so work stays attributable to the session that produced it:
95
139
 
96
140
  ```html
97
141
  <!-- legion: {"session":"<session-id>","phase":"<phase>"} -->
@@ -107,71 +151,132 @@ legion gh -- issue comment <issue-number> \
107
151
 
108
152
  ## Implementer push and pull request
109
153
 
110
- Only the implementer creates the issue bookmark, pushes it, and opens the pull request. After
111
- its implementation commit and verification, it uses this exact branch name and push procedure:
154
+ Only the implementer creates the issue bookmark, pushes it, and opens the pull request.
155
+ After its implementation commit and verification, it uses this exact branch name and push
156
+ procedure:
112
157
 
113
158
  ```bash
114
- cd -- "<workspace>" && \
115
- jj -R "<workspace>" bookmark set legion/issue-<n> && \
116
- jj -R "<workspace>" git push --bookmark legion/issue-<n> --allow-new
159
+ cd -- "$LEGION_WORKSPACE" && \
160
+ jj -R "$LEGION_WORKSPACE" bookmark set legion/issue-<n> && \
161
+ jj -R "$LEGION_WORKSPACE" git push --bookmark legion/issue-<n> --allow-new
117
162
  ```
118
163
 
119
164
  The provisioned issue workspace configures `credential.helper` with the daemon's absolute
120
- credential command, so `jj -R "<workspace>" git push` authenticates transparently through the
121
- same session capability. Never handle a token.
165
+ credential command, so `jj -R "$LEGION_WORKSPACE" git push` authenticates transparently
166
+ through the same session capability. Never handle a token.
122
167
 
123
168
  Then create the pull request with the `github` tool's `pr_create` operation. The credential
124
- helper and `legion gh` provide the GitHub identity; never export, fetch, or replace a token.
125
- Other phases advance the existing branch rather than creating a replacement bookmark or PR.
169
+ helper and `legion gh` provide the GitHub identity; never export, fetch, or replace a
170
+ token. Other phases advance the existing branch rather than creating a replacement
171
+ bookmark or PR.
126
172
 
127
- ## Completion gate: handoff write, verification, and persistence
173
+ ## PR body and merge-queue discipline
174
+
175
+ The implementer writes the PR body in the merge queue's READY format from the moment the
176
+ PR opens, and every later phase keeps it current rather than replacing it:
177
+
178
+ ```
179
+ ## Verification
180
+
181
+ **CI:** `pr-checks-result` run <run-id> — success at <head-sha>.
182
+
183
+ **Threads:** <n> resolved, 0 unresolved. Each disposed individually, never in bulk:
184
+ - Thread <id>: fixed in <commit-sha> — <one line>.
185
+ - Thread <id>: not a defect — <reason>.
186
+
187
+ **Thermo:** thermonuclear-deep-review + thermonuclear-code-quality run once at <head-sha>:
188
+ <verdict>. (omitted entirely on a docs-only PR — no thermo pass runs)
189
+
190
+ **E2E:** <surface> — ran `<command or run id>`, observed <result>, at head <sha>.
191
+ Negative control: <deliberately broken input> → <refusal or failure observed>.
128
192
 
129
- The durable handoff uses the phase-specific fields from the task's `outputSchema` only.
130
- `--data` must not include `schemaVersion`, `phase`, or `completed`: the CLI generates that
131
- envelope. Return the **full** schema through the task's structured output, including the
132
- generated envelope fields.
193
+ **Fast-follow:** <one named cleanup item and where it will land>, or "none".
194
+
195
+ **Chain:** stacked on <base bookmark> frozen at <sha> / not stacked.
196
+ ```
197
+
198
+ - **Threads are dispositioned individually, never resolved in bulk.** Every open review
199
+ thread gets its own line naming the fixing commit or the reason it isn't a defect before
200
+ it is marked resolved.
201
+ - **Correctness fixes land in this PR; cleanup is one named fast-follow.** A finding that
202
+ changes behavior, hides an error, or breaks a gate is fixed here — never deferred.
203
+ Findings about naming, duplication, or wording are batched into the single `Fast-follow`
204
+ line instead of iterating per push.
205
+ - The tester fills in the `E2E` section: the real surface a user reaches the criterion
206
+ through, the exact command or run id, what was observed, the head SHA, and one negative
207
+ control — a deliberately broken input and the refusal or failure it produced. A unit or
208
+ integration test is a regression lock, never proof of a criterion.
209
+ - The reviewer verifies the `CI`, `Threads`, and `E2E` facts against GitHub directly —
210
+ never from a handoff — then runs `task(agent="thermonuclear-deep-review")` and
211
+ `task(agent="thermonuclear-code-quality")` once at that head and records the verdict.
212
+ Skip the `Thermo` line entirely on a docs-only PR. Post every correctness finding as a
213
+ PR review comment and return the issue to the architect; when clean, delete `.legion/`,
214
+ push, review **that** head, and approve it by name.
215
+ - Once a base is frozen for others to stack on, never rewrite it — fixes land as new
216
+ commits on top, and the `Chain` line records what is frozen.
217
+ - The merger confirms the approved head still equals the current head, then publishes
218
+ `READY #<n> at <sha>` plus the PR body's gate facts to the merge queue's role
219
+ (`notifications.role.pr-queue`) with `envoy_publish`. The merger never merges; the queue
220
+ merges under its own authority.
221
+
222
+ ## Completion gate: handoff write, verification, and persistence
133
223
 
134
224
  Write the phase-specific handoff:
135
225
 
136
226
  ```bash
137
- cd -- "<workspace>" && \
227
+ cd -- "$LEGION_WORKSPACE" && \
138
228
  legion handoff write --phase <p> --data '<JSON object of phase-specific fields only>'
139
229
  ```
140
230
 
141
231
  Then verify the durable artifact exists:
142
232
 
143
233
  ```bash
144
- test -f "<workspace>/.legion/<phase>.json"
234
+ test -f "$LEGION_WORKSPACE/.legion/<phase>.json"
145
235
  ```
146
236
 
147
237
  Then commit that exact handoff file onto the issue branch:
148
238
 
149
239
  ```bash
150
- cd -- "<workspace>" && \
151
- jj -R "<workspace>" split -m "<phase>: record handoff" .legion/<phase>.json
240
+ cd -- "$LEGION_WORKSPACE" && \
241
+ jj -R "$LEGION_WORKSPACE" split -m "<phase>: record handoff" .legion/<phase>.json
152
242
  ```
153
243
 
154
- If the issue bookmark exists locally, advance it and push it with the provisioned credential
155
- helper. `--allow-new` also publishes the locally provisioned bookmark on its first push:
244
+ If the issue bookmark exists locally, advance it and push it with the provisioned
245
+ credential helper. `--allow-new` also publishes the locally provisioned bookmark on its
246
+ first push:
156
247
 
157
248
  ```bash
158
- cd -- "<workspace>" && \
159
- jj -R "<workspace>" bookmark set legion/issue-<n> && \
160
- jj -R "<workspace>" git push --bookmark legion/issue-<n> --allow-new
249
+ cd -- "$LEGION_WORKSPACE" && \
250
+ jj -R "$LEGION_WORKSPACE" bookmark set legion/issue-<n> && \
251
+ jj -R "$LEGION_WORKSPACE" git push --bookmark legion/issue-<n> --allow-new
161
252
  ```
162
253
 
163
- Do not report phase completion until the write, existence check, and handoff commit succeed;
164
- when an issue branch exists, its push is also required. This is the committed copy the next
165
- phase reads after revival. The reviewer later removes `.legion/` as its final commit; phase
166
- workers do not remove it.
254
+ Do not report phase completion until the write, existence check, and handoff commit
255
+ succeed; when an issue branch exists, its push is also required. This is the committed
256
+ copy the next phase reads after revival. The reviewer later removes `.legion/` as its final
257
+ commit; phase workers do not remove it.
258
+
259
+ ## Completion: report to the architect, then stay
167
260
 
168
- ## Completion and escalation
261
+ Report completion to the architect with:
169
262
 
170
- Return the same schema as the durable handoff through the task's structured output. Do not add
171
- pipeline labels, run a controller loop, or notify a controller with an invented completion
172
- protocol. A direct worker delivery belongs to its role; overseers receive only derived
173
- verdicts.
263
+ ```bash
264
+ cd -- "$LEGION_WORKSPACE" && \
265
+ legion handoff complete --summary '<two sentences for the architect>'
266
+ ```
174
267
 
175
- When blocked on lifecycle, scope, or cross-phase matters, send the owning architect a concise
176
- hub message: issue, phase, verified observation, what you tried, and the decision required.
177
- Reach for `dispatch` yourself only for a standalone human question outside that coordination.
268
+ This publishes your phase's completion to the architect's role and clears the daemon's
269
+ record of this issue's active phase. Do not add pipeline labels, run a controller loop, or
270
+ invent a different completion protocol this is the whole contract.
271
+
272
+ **Stay in this session afterward.** Your process does not exit when your phase completes;
273
+ it goes idle in its pane. Other roles on this issue may reach you through Envoy with
274
+ questions about the work you did — answer them, reading `$LEGION_WORKSPACE` and your own
275
+ committed handoff as needed, without mutating anything (see Workspace and handoff
276
+ precedence above). You will also be the one resumed, with a new prompt in this same
277
+ session, if this phase's work needs to run again.
278
+
279
+ When blocked on lifecycle, scope, or cross-phase matters, `envoy_publish` the owning
280
+ architect a concise message: issue, phase, verified observation, what you tried, and the
281
+ decision required. Reach for `dispatch` yourself only for a standalone human question
282
+ outside that coordination.
@@ -1,259 +0,0 @@
1
- # Repository Configuration (.legion/config.yml)
2
-
3
- Workers load repository-specific configuration from `.legion/config.yml` at the workspace root. This file allows teams to customize Legion behavior per repository without modifying workflows.
4
-
5
- ## Schema Overview
6
-
7
- The config file is YAML with the following top-level sections:
8
-
9
- ```yaml
10
- merge:
11
- require_smoke_test: boolean
12
- require_reporter_approval: boolean
13
- auto_merge_allowed: boolean
14
-
15
- testing:
16
- require_specific_task: boolean
17
- require_taiga_evidence: boolean
18
-
19
- notifications:
20
- slack_channel: string
21
- ping_reporter_on_pr: boolean
22
-
23
- skills:
24
- required:
25
- - skill_name_1
26
- - skill_name_2
27
-
28
- phases:
29
- architect:
30
- # Phase-specific overrides (same keys as top-level)
31
- plan:
32
- # Phase-specific overrides
33
- implement:
34
- # Phase-specific overrides
35
- test:
36
- # Phase-specific overrides
37
- review:
38
- # Phase-specific overrides
39
- ```
40
-
41
- ## Field Reference
42
-
43
- ### merge
44
-
45
- Controls merge behavior and approval gates.
46
-
47
- | Field | Type | Default | Description |
48
- |-------|------|---------|-------------|
49
- | `require_smoke_test` | boolean | `false` | If `true`, merge workflow requires evidence of smoke testing before auto-merge |
50
- | `require_reporter_approval` | boolean | `false` | If `true`, merge workflow requires explicit reporter approval before merging |
51
- | `auto_merge_allowed` | boolean | `false` | If `true`, merge workflow may auto-merge PRs that pass all gates |
52
-
53
- ### testing
54
-
55
- Controls test requirements and evidence gates.
56
-
57
- | Field | Type | Default | Description |
58
- |-------|------|---------|-------------|
59
- | `require_specific_task` | boolean | `false` | If `true`, test workflow requires evidence of specific task testing (not just unit tests) |
60
- | `require_taiga_evidence` | boolean | `false` | If `true`, test workflow requires Taiga evidence (e.g., screenshots, logs) attached to the issue |
61
-
62
- ### notifications
63
-
64
- Controls notifications and pings.
65
-
66
- | Field | Type | Default | Description |
67
- |-------|------|---------|-------------|
68
- | `slack_channel` | string | `null` | Slack channel ID (e.g., `#eng-legion`) where implementation status updates are posted. If set and `slack-bot` skill is available, implement workflow posts PR URL and CI state |
69
- | `ping_reporter_on_pr` | boolean | `false` | If `true`, notify the issue reporter when a PR is created |
70
-
71
- ### skills
72
-
73
- Specifies skills that should be invoked for all phases.
74
-
75
- | Field | Type | Default | Description |
76
- |-------|------|---------|-------------|
77
- | `required` | string[] | `[]` | List of skill names to invoke in addition to plan handoff `requiredSkills` and independently discovered skills. Additive with other skill sources |
78
-
79
- ### phases
80
-
81
- Phase-specific overrides. Each phase (`architect`, `plan`, `implement`, `test`, `review`) can override any top-level key.
82
-
83
- **Merge behavior:** Phase-specific values override top-level values. For example:
84
-
85
- ```yaml
86
- merge:
87
- require_reporter_approval: false
88
-
89
- phases:
90
- implement:
91
- merge:
92
- require_reporter_approval: true # Override for implement phase only
93
- ```
94
-
95
- ## Recognized Keys
96
-
97
- Workers recognize the following keys (case-sensitive):
98
-
99
- - `merge.require_smoke_test`
100
- - `merge.require_reporter_approval`
101
- - `merge.auto_merge_allowed`
102
- - `testing.require_specific_task`
103
- - `testing.require_taiga_evidence`
104
- - `notifications.slack_channel`
105
- - `notifications.ping_reporter_on_pr`
106
- - `skills.required`
107
- - `phases.<mode>.*` (any of the above keys under a phase)
108
-
109
- Unknown keys are silently ignored. Malformed YAML causes the config to be skipped (fallback to defaults).
110
-
111
- ## Worker Behavior
112
-
113
- ### Loading
114
-
115
- Each workflow loads config at startup:
116
-
117
- ```bash
118
- if [ -f .legion/config.yml ]; then cat .legion/config.yml; fi
119
- ```
120
-
121
- If the file is missing or malformed, workers proceed with defaults (no error).
122
-
123
- ### Parsing
124
-
125
- Workers parse recognized keys and echo them for auditability:
126
-
127
- ```
128
- Repo config constraints from .legion/config.yml:
129
- - merge.require_reporter_approval: true
130
- - testing.require_specific_task: true
131
- - skills.required: [test-driven-development, verification-before-completion]
132
- ```
133
-
134
- ### Application
135
-
136
- Config values are applied to shape workflow behavior:
137
-
138
- - **Plan phase:** Config constraints inform the plan preamble (e.g., "reporter approval required before merge")
139
- - **Implement phase:** Config-required skills are invoked additively with plan handoff skills
140
- - **Test phase:** Config gates (e.g., `require_specific_task`) are enforced
141
- - **Review phase:** Config-required skills are invoked additively
142
- - **Merge phase:** Config gates (e.g., `require_reporter_approval`) are enforced
143
-
144
- ## Example Configuration
145
-
146
- ### Minimal (all defaults)
147
-
148
- ```yaml
149
- # Empty file or omitted entirely
150
- # All defaults apply
151
- ```
152
-
153
- ### Strict Testing
154
-
155
- ```yaml
156
- testing:
157
- require_specific_task: true
158
- require_taiga_evidence: true
159
-
160
- skills:
161
- required:
162
- - test-driven-development
163
- - verification-before-completion
164
- ```
165
-
166
- ### Slack Notifications + Approval Gate
167
-
168
- ```yaml
169
- notifications:
170
- slack_channel: "#eng-legion"
171
- ping_reporter_on_pr: true
172
-
173
- merge:
174
- require_reporter_approval: true
175
- require_smoke_test: true
176
- ```
177
-
178
- ### Phase-Specific Overrides
179
-
180
- ```yaml
181
- # Default: no approval required
182
- merge:
183
- require_reporter_approval: false
184
-
185
- # But for implement phase, require approval
186
- phases:
187
- implement:
188
- merge:
189
- require_reporter_approval: true
190
-
191
- # And require specific task testing only in test phase
192
- phases:
193
- test:
194
- testing:
195
- require_specific_task: true
196
- ```
197
-
198
- ### Full Example
199
-
200
- ```yaml
201
- merge:
202
- require_smoke_test: true
203
- require_reporter_approval: false
204
- auto_merge_allowed: false
205
-
206
- testing:
207
- require_specific_task: true
208
- require_taiga_evidence: false
209
-
210
- notifications:
211
- slack_channel: "#eng-legion"
212
- ping_reporter_on_pr: true
213
-
214
- skills:
215
- required:
216
- - test-driven-development
217
- - verification-before-completion
218
-
219
- phases:
220
- plan:
221
- skills:
222
- required:
223
- - brainstorming
224
- implement:
225
- merge:
226
- require_reporter_approval: true
227
- test:
228
- testing:
229
- require_taiga_evidence: true
230
- ```
231
-
232
- ## Defaults
233
-
234
- If a key is not specified in `.legion/config.yml`, the following defaults apply:
235
-
236
- ```yaml
237
- merge:
238
- require_smoke_test: false
239
- require_reporter_approval: false
240
- auto_merge_allowed: false
241
-
242
- testing:
243
- require_specific_task: false
244
- require_taiga_evidence: false
245
-
246
- notifications:
247
- slack_channel: null
248
- ping_reporter_on_pr: false
249
-
250
- skills:
251
- required: []
252
- ```
253
-
254
- ## Notes
255
-
256
- - **Additive skills:** Config-required skills are additive with plan handoff `requiredSkills` and independently discovered skills. All sources are combined.
257
- - **Phase overrides:** Phase-specific values completely override top-level values for that phase. Partial overrides are not merged.
258
- - **Missing file:** If `.legion/config.yml` is missing or malformed, workers proceed with defaults (no error).
259
- - **Auditability:** Workers echo recognized keys and effective values at the start of each phase for transparency.