@sjawhar/opencode-legion-envoy 8.30.0 → 8.30.2

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.
Files changed (34) hide show
  1. package/package.json +1 -1
  2. package/skills/envoy/SKILL.md +47 -286
  3. package/skills/envoy/references/check-settlement.md +62 -0
  4. package/skills/envoy/references/deliveries.md +62 -0
  5. package/skills/envoy/references/legion.md +12 -0
  6. package/skills/envoy/references/roles.md +10 -0
  7. package/skills/envoy/references/sources.md +41 -0
  8. package/skills/legion-architect/SKILL.md +41 -419
  9. package/skills/legion-architect/references/acceptance.md +153 -0
  10. package/skills/legion-architect/references/decomposition.md +77 -0
  11. package/skills/legion-architect/references/design-gate.md +148 -0
  12. package/skills/legion-architect/references/wake-routing.md +11 -6
  13. package/skills/legion-controller/SKILL.md +96 -469
  14. package/skills/legion-controller/references/admission.md +7 -6
  15. package/skills/legion-controller/references/backlog-stewardship.md +32 -27
  16. package/skills/legion-controller/references/daily-report.md +72 -0
  17. package/skills/legion-controller/references/escalation.md +37 -0
  18. package/skills/legion-controller/references/finding-asks.md +32 -14
  19. package/skills/legion-controller/references/session.md +98 -0
  20. package/skills/legion-controller/references/slack-mentions.md +10 -9
  21. package/skills/legion-controller/references/triage.md +81 -0
  22. package/skills/legion-controller/references/wakes.md +90 -0
  23. package/skills/legion-oracle/SKILL.md +26 -57
  24. package/skills/legion-retro/SKILL.md +116 -240
  25. package/skills/legion-retro/references/learnings.md +58 -0
  26. package/skills/legion-retro/references/pr-body-content.md +78 -0
  27. package/skills/legion-worker/SKILL.md +40 -462
  28. package/skills/legion-worker/references/conflicts-and-rewrites.md +2 -2
  29. package/skills/legion-worker/references/default-branch-check.md +16 -0
  30. package/skills/legion-worker/references/findings.md +2 -2
  31. package/skills/legion-worker/references/pr-body.md +1 -1
  32. package/skills/legion-worker/references/review-threads.md +1 -1
  33. package/skills/thermonuclear-code-quality/SKILL.md +34 -82
  34. package/skills/thermonuclear-deep-review/SKILL.md +34 -33
@@ -5,481 +5,59 @@ description: Use when dispatched as a per-process Legion phase worker — planne
5
5
 
6
6
  # Legion Phase Worker
7
7
 
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.
8
+ If this skill disagrees with the code, a command's output or its `--help`, follow those and say which line of this skill is wrong.
13
9
 
14
- Every path this skill cites (`packages/...`, `docs/...`, `AGENTS.md`) is in sjawhar/legion, the
15
- Legion repository, which need not be the repository you are working in.
10
+ You work one phase of one issue in a jj workspace every role of the issue shares; the architect owns the tree. Your role prompt gives the workspace binding, `gh`, the push, the handoff file, `handoff_complete` and how long your session stays; this skill adds the rest.
11
+
12
+ ## Every phase, in this order
13
+
14
+ 1. **Read first.** Read the issue, then each committed handoff before your phase, with `read` from `$LEGION_WORKSPACE/.legion/<issue>/`, in order: `plan.json`, `implement.json`, `test.json`, `review.json`. Where one disagrees with your memory or a transcript, the file wins: it is the copy that survived. At each later assignment read them again, your own included, since other phases may have committed since. After a `Your workspace was recreated…` message, read `.legion/<issue>/workspace-recovered.json` too, once.
15
+ 2. **Commit only your phase's work**, with `jj -R "$LEGION_WORKSPACE" split -m "<message>" <paths…>`, each commit holding only your phase's paths, so the next phase sees what you changed.
16
+ 3. **Put back what you copied in.** Before you write the handoff, run `jj -R "$LEGION_WORKSPACE" status` and remove or restore every file you copied or fetched in that is not your phase's work, such as another branch's test rig. With jj the working copy is the commit: the next role's first commit builds on what you left, and its push ships it.
17
+ 4. **Write the handoff** your role prompt names. Each `proof` entry, the implementer's or the tester's, is an object of six non-empty strings: `criterion` (the acceptance line it proves), `surface` (where a user reaches the change), `command`, `observed`, `headSha` (the commit it ran at) and `negativeControl` (a deliberately broken input and the refusal seen); `skill://legion-worker/references/pr-body.md#what-a-proof-is` defines each. To add to a handoff already on disk, `read` it, edit it, and `write` it whole with `completed` set to now.
18
+ 5. **Push, then complete**, as the push section below says. `handoff_complete` is your only way to end a phase: add no label, keep no status of your own and run no loop of your own, since the daemon owns the issue's state and the architect its decomposition and gates.
19
+
20
+ ## Stop rules
21
+
22
+ - **A refused completion is information, not a retry loop.** Quote the answer verbatim to the architect, so "my work is lost" and "my work belongs to an ended run" read differently. `HANDOFF_STALE_GENERATION` (the issue is on a newer run, or your turn began before the daemon recorded your task, which it then sends again) or `HANDOFF_NO_RUN` (your claim holds no task): push nothing further and tell the architect; when a task then arrives whose work is already committed, call `handoff_complete` again, and never redo the work or write a second handoff. `HANDOFF_NOT_CURRENT_PHASE`: the issue left your phase; report, never complete again. `HANDOFF_ALREADY_RECORDED`: the first answer stands, an acceptance or one of the four refusals the daemon records (`HANDOFF_STALE_GENERATION`, `HANDOFF_NOT_CURRENT_PHASE`, `READY_REQUIRED`, `HANDOFF_NOT_NEW`); if you did not see it, tell the architect. A refusal given before any fact is applied (READY's checks of the head among them) records nothing, so the corrected call at the same commit is applied. A reminder is not a task: after an accepted completion, a second call is refused.
23
+ - **After your phase completes, the workspace is read-only for you**: no commit, no `jj new`, no edit to a tracked file, in any later turn until a new task names your phase. The active phase owns it, and you stay live only to answer questions.
24
+ - **Never start another Legion role**: the daemon starts every phase worker.
25
+ - **Never end your turn blocked on a decision someone else owns.** Send a product, scope, design, lifecycle or cross-phase decision to the owning architect as your role prompt says, with the issue, phase, verified observation, what you tried and the decision needed; a human-only to-do is a `dispatch ask`. Otherwise proceed: a phase that stops silently holds its issue until someone notices.
26
+ - **No surface reaches the changed path** is a report to the architect, never a reason to complete (`skill://legion-worker/references/pr-body.md#when-no-surface-reaches-the-changed-path`).
27
+ - **Asking another role**: if its topic answers 404, read its committed handoff instead.
16
28
 
17
29
  ## References
18
30
 
19
- Each file below is part of this skill. Read it at the step beside it, through its `skill://` link
20
- with the `read` tool: a read by filesystem path stops at 300 lines.
31
+ Read each by its `skill://` link: a read by path stops at 300 lines.
21
32
 
22
33
  | When | Read |
23
34
  | --- | --- |
24
- | You write or edit the PR body, record a proof (an `E2E` line or a handoff `proof` array), verify another phase's proof, or run the simplify pass | `skill://legion-worker/references/pr-body.md` |
25
- | Before a push, to check your commits' App identity against your issue's default branch | `skill://legion-worker/references/default-branch-check.md` |
26
- | You reply on or resolve a review thread, list a pull request's threads, or adjudicate a bot's finding | `skill://legion-worker/references/review-threads.md` |
27
- | GitHub reports a conflict, the pull request is retargeted, you compare heads after a conflict merge, or you would rewrite a pushed commit | `skill://legion-worker/references/conflicts-and-rewrites.md` |
28
- | You write the `skip-checks: true` trailer on a handoff-only push, or expect a pull-request body edit to re-run a check | `skill://legion-worker/references/skip-checks-trailer.md` |
29
- | You review or approve, build the READY packet, or check the merge in production | `skill://legion-worker/references/merge-gate.md` |
35
+ | You write or edit the PR body, record or verify a proof, or run the simplify pass | `skill://legion-worker/references/pr-body.md` |
36
+ | Before a push, to check your commits' App identity | `skill://legion-worker/references/default-branch-check.md` |
37
+ | You reply on, list or resolve review threads, or judge a bot's finding | `skill://legion-worker/references/review-threads.md` |
38
+ | A conflict, a retarget, comparing heads after a conflict merge, or rewriting a pushed commit | `skill://legion-worker/references/conflicts-and-rewrites.md` |
39
+ | You write the `skip-checks: true` trailer, or expect a body edit to re-run a check | `skill://legion-worker/references/skip-checks-trailer.md` |
40
+ | You review or approve, build READY, or run the production check | `skill://legion-worker/references/merge-gate.md` |
30
41
  | The issue renames a repository, package, or URL across the codebase | `skill://legion-worker/references/systematic-rename.md` |
31
42
  | The issue deletes code, a command, or documentation | `skill://legion-worker/references/cleanup-deletion.md` |
32
- | Your phase needs a tool — a client, a linter, a CLI — that the image may not carry | `skill://legion-worker/references/tools.md` |
33
- | You find a problem outside your issue, or the production check fails | `skill://legion-worker/references/findings.md` |
34
-
35
- ## Identity, scope, and role
36
-
37
- The daemon spawns you as a separate `omp --mode rpc` process (behind `legion worker-shim`,
38
- in a tmux pane or an Agent Sandbox pod) with `LEGION_TREE`, `LEGION_ISSUE`, `LEGION_ROLE`,
39
- `LEGION_GENERATION`, `LEGION_PROJECT`, `LEGION_BOOT_TOKEN_FILE` (the file holding your boot
40
- token; the extension reads it for you), `LEGION_DAEMON_URL`, `LEGION_STATE_DIR`, and
41
- `LEGION_WORKSPACE` in your environment. The extension completes the boot handshake for you at
42
- session start — it registers with the daemon, claims your role, and signals readiness. You never
43
- call `envoy_role_set` yourself.
44
-
45
- Your role token is not the issue key spelled out literally. The daemon encodes it as
46
- `legion-<project>-<key>-<role>` with the issue key lower-cased. For example, project `acme`, issue
47
- `LEGION-41`, role `architect` encodes to `legion-acme-legion-41-architect`. Never hand-format one for another role: your own role
48
- topic and the topic of the architect that owns your issue are in the `Legion addressing` line of
49
- your system prompt (the daemon appends it; it names the tree root's architect, also on a child
50
- issue), a sibling role's topic is yours with the trailing `-<role>` replaced, and the `roleToken`
51
- helper in `@legion/contracts` computes any other one exactly the way the daemon does — prefer a
52
- topic you've already been given before recomputing one.
53
-
54
- If the handshake fails (a rejected boot token, or a bootstrap failure after your role
55
- registered), the extension logs it and exits the process outright — it does not retry, and
56
- you do not troubleshoot it by hand. The daemon resumes this same session from its recorded
57
- session file the next time this role is needed; that is not an instant automatic respawn.
58
-
59
- Once ready, your assignment arrives as the first prompt in your session — you do not fetch
60
- it. Read the current issue and its acceptance criteria before changing the workspace. Work
61
- only on this phase's artifact.
62
-
63
- You never start another Legion role: the daemon starts every phase worker itself, from its fixed
64
- workflow table. You may still use ordinary `task` subagents for your own phase work; none of them
65
- is a Legion role. A subagent runs in your pane as you, with every host tool but the `legion` tool
66
- (it is never offered one), so completing your phase is yours alone: give a subagent no completion
67
- step. Escalate a product, scope, design, cross-phase, or lifecycle decision to the owning architect
68
- with `envoy_publish` to its role topic (`notifications.role.` followed by its encoded token, see
69
- above), carrying the verified facts and the decision needed. A `write` to `agent://` only reaches
70
- agents inside your own process, not the architect's separate one. Never write a decision block
71
- into a spec yourself: the architect decides whether the human must answer it and writes the block,
72
- since a new version of an approved root spec closes the tree's design gate. A standalone to-do
73
- only a human can do is a `dispatch ask`, and its replies return to your own session. So is a
74
- problem outside your tree, never an issue you file: `skill://legion-worker/references/findings.md`.
75
-
76
- Because the same agent works its role until the issue closes, you may receive more than one
77
- assignment across your lifetime: your session stays live after your phase ends, and when a later
78
- event (a review round, a red check) starts your role again the new prompt arrives in this same
79
- session. Treat it as a continuation — re-read the current issue and your own prior handoff, since
80
- time has passed — never as a fresh identity.
81
-
82
- ## Deployment instructions
83
-
84
- Deployment instructions, when present, are the operator's standing rules for this repository —
85
- required checks, deploy/smoke commands, code-owner expectations, standing roles you may consult,
86
- the merge credential. They override this skill's defaults where they conflict, except four rules
87
- they never override: no deferrals (*PR body, review, and the merge gate*, below); bringing the base
88
- into the branch only on a real conflict or a retarget
89
- (`skill://legion-worker/references/conflicts-and-rewrites.md#reintegrating-the-base`); the
90
- implementer's own proof on a production-like surface at the head that merges, an applied simplify
91
- head included (`skill://legion-worker/references/pr-body.md#what-a-proof-is`,
92
- `skill://legion-worker/references/pr-body.md#the-rules-every-phases-evidence-follows`); and the
93
- implementer's production check after the merge closes the issue
94
- (`skill://legion-worker/references/merge-gate.md#the-production-check-after-the-close`).
95
-
96
- ## Asking another role
97
-
98
- Reach any live role on this issue the same way you reach the architect: `envoy_publish` to
99
- `notifications.role.` followed by that role's encoded token. Use it when you need context an
100
- earlier phase has that its handoff doesn't cover — ask the planner why a constraint was
101
- scoped that way, ask the implementer what a commit actually did. A role that finished its phase
102
- stays live and answers until its issue leaves the workflow. If a publish is rejected with 404,
103
- read that role's committed handoff.
104
-
105
- ## Workspace and handoff precedence
106
-
107
- `LEGION_WORKSPACE` is the authoritative issue workspace. Before reading repository files or
108
- handoffs, you **MUST** bind to that exact path with:
109
-
110
- ```bash
111
- cd -- "$LEGION_WORKSPACE" && jj -R "$LEGION_WORKSPACE" status
112
- ```
113
-
114
- Never rely on the inherited cwd. Every later repository shell command **MUST** begin
115
- `cd -- "$LEGION_WORKSPACE" &&`; every jj command **MUST** use `-R "$LEGION_WORKSPACE"`; and
116
- native filesystem tool paths **MUST** be absolute under that workspace. Do not create an
117
- isolated worktree, change the workspace topology, or mix another issue's work into it.
118
- Concurrent issues have disjoint workspaces; only the currently active phase mutates this
119
- one. After you complete and go idle, treat `$LEGION_WORKSPACE` as read-only in every later
120
- turn, including one an Envoy question starts: you are kept alive to answer questions, not to keep
121
- editing. Do not create new commits, run `jj -R "$LEGION_WORKSPACE" new`, or touch tracked files
122
- once your own handoff is committed and pushed — a code change belongs to
123
- whichever phase is active now. The same holds once the Go daemon has taken your phase back without
124
- your completion: CI settling red while you tested, reviewed a round you had not completed, or
125
- built READY, moves the issue to `implementing` and interrupts your turn, and the implementer starts
126
- only once that turn has ended. Do not resume the interrupted work afterward. From retro the
127
- issue moves the same way with nothing interrupted: you are the implementer, handed the implementing
128
- task once your turn ends; a retro completion started after the move is refused, and one in flight
129
- when the red lands can be taken as your implementing completion, caught by the tester's CI read.
130
-
131
- On every start, and especially after revival or re-creation, read the issue and then the
132
- committed predecessor handoffs in lifecycle order, with the `read` tool from
133
- `$LEGION_WORKSPACE/.legion/<issue>/`:
134
-
135
- 1. `plan.json`
136
- 2. `implement.json`
137
- 3. `test.json`
138
- 4. `review.json`
139
-
140
- Read only files that precede the assigned phase. Each was checked against its phase's rules when
141
- its phase completed (the completion gate below): fields the phase does not declare passed untouched
142
- and reach the next worker. Write the phase-specific fields the next phase and the architect need,
143
- consistent with what predecessor phases already wrote. The durable copy lives in
144
- `$LEGION_WORKSPACE/.legion/<issue>/<phase>.json`. If a committed handoff conflicts with memory or a
145
- prior transcript, the committed file wins: it is the copy that survived.
146
-
147
- If your task, prompt, or a message since your last turn begins `Your workspace was recreated…`, read
148
- your phase's committed handoff and any `.legion/<issue>/workspace-recovered.json`, and reconcile
149
- before new work: anything unpushed is gone. That message stays in history; reconciled, it is done.
150
-
151
- ## Phase work
152
-
153
- 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.
154
-
155
- Follow the repository's normal engineering workflow and the assigned issue's acceptance
156
- criteria. Your phase's own charter and the predecessor handoffs you read define the phase
157
- artifact and its completion evidence. Do not replace architect-owned decomposition, gate
158
- discipline, scheduling, or human communication with labels or a local status model.
159
- An issue that renames a repository, package, or URL across the codebase also follows
160
- `skill://legion-worker/references/systematic-rename.md`; one that deletes code, a command, or
161
- documentation follows `skill://legion-worker/references/cleanup-deletion.md`.
162
-
163
- Create reviewable commits with `jj -R "$LEGION_WORKSPACE" split -m "<message>" <paths…>`, each holding only your phase's paths.
164
-
165
- Commit attribution is automatic: the extension exports a `JJ_CONFIG` overlay when your
166
- session starts, so every jj commit you make carries an `Omp-Session: <this-session-id>`
167
- trailer with no action from you. Do not add attribution trailers by hand.
168
-
169
- Your pane's environment already supplies your phase's author and committer identity (`JJ_USER`/`JJ_EMAIL` and the Git author/committer variables, set by the daemon when it opened the pane).
170
- Before your turn's first commit, run `jj -R "$LEGION_WORKSPACE" log -r @ --no-graph -T 'empty'`.
171
- If it prints `true`, run `jj -R "$LEGION_WORKSPACE" new @-`; if it prints `false`, `@` holds only
172
- your own resumed edits, so run `jj -R "$LEGION_WORKSPACE" new`. Never `jj describe` or `jj split`
173
- the working-copy commit you found at the start of your turn: it can carry the previous role's
174
- author, and those commands keep it. Never set or override `user.name`/`user.email`
175
- in any jj or Git scope — not `jj config set`, not `--config`, not `git config`: `--config` outranks
176
- the pane environment and would put the wrong App back on your commits, and the repository-scoped jj
177
- config is one file shared by every issue workspace of the clone. Legion has two GitHub Apps, not
178
- one per role: your role's App is the **implement** App if you are the implementer or the merger,
179
- and the **review** App if you are the planner, tester, reviewer, or an architect; your pane's
180
- `JJ_USER` and `JJ_EMAIL` name your role's App's bot account. A planner's commits authored
181
- by the review App are right. Before a push, check your commits against your issue's own default
182
- branch, read and quoted safely (never a branch name pasted into shell source), per `skill://legion-worker/references/default-branch-check.md`, which shows your role's App in both columns **on every commit you made** — not on the whole list:
183
- earlier phases' commits are legitimately authored by their own role's App. Their *committer* is
184
- a different matter, and no longer noise to accept. Resolving a conflict rewrites nothing — it is a
185
- forward merge (`skill://legion-worker/references/conflicts-and-rewrites.md`) — so it changes no
186
- committer at all, and the one rewrite still open to you (*Rewriting pushed commits*, in the same
187
- reference) resets the committer only of commits on your own chain that descend from the commit
188
- you named, after its guard cleared. Another role's commit
189
- carrying you as committer, which you did not rewrite that way, is evidence that something
190
- rewrote commits it should not have. Stop and send the
191
- architect that log; do not accept it as a side effect. A wrong identity on your own commit, the
192
- other App or none, is a pane-environment problem to report to the architect, not something to
193
- pin (`docs/solutions/legion/shared-main-repo-hazards-for-concurrent-issue-workspaces.md`,
194
- Hazard 1).
195
- Your pane's `gh` and `git` already carry your role's GitHub identity; invoke GitHub with plain
196
- `gh`:
197
-
198
- ```bash
199
- gh <gh args…>
200
- ```
201
-
202
- How `gh` works in a worker pane. `LEGION_GH_OWNERS_DIR` holds one read-only gh directory per
203
- GitHub owner of the project (`hosts.yml`, an App installation token, and `config.yml`), which the
204
- daemon rewrites in place so no token expires under you: your issue's owner's, which `GH_CONFIG_DIR`
205
- names, holds your role's App token; every other owner's the same App's, read-only. Your `gh` picks
206
- the directory of the owner a command names (`-R owner/repo`, `repos/owner/repo` in `gh api`, a
207
- GitHub URL), your issue's owner's otherwise, so name the repository whenever it is not your
208
- issue's; `git` picks by the remote URL's owner (`!legion git-credential`). `GH_TOKEN`,
209
- `GITHUB_TOKEN` and `GH_HOST` are empty so nothing outranks the files. Never run `gh auth login`,
210
- `gh auth switch`, `gh auth setup-git`, `gh config set` or `gh alias set`: there is no login state
211
- to create. One rule nothing enforces: **Legion's issues live on Dispatch, never on
212
- GitHub issues** — no `gh issue` write and no non-GET `gh api` call to an `/issues` path
213
- (pull-request conversation comments live on that path too; edit them with `gh pr comment`); use
214
- `dispatch message` or `dispatch comment` on your `LEGION_ISSUE`. The `legion` tool's own daemon
215
- calls carry a credential of their own, minted in-process; `gh` and `git` never see it, and you
216
- never `cat`, `echo`, copy, or `export` a token; a `task` subagent or background job inherits them.
217
-
218
- **Other credentials your pod may already carry.** Before reporting that a read is unreachable,
219
- check for them rather than assuming none exist: `AGENT_SECRETS_URL` and `AGENT_SECRETS_KEY_DIR`
220
- are set when the deployment enrolls pods with the agent-secrets broker (`docs/kubernetes.md`,
221
- "Operator configuration"), in which case `agent-secrets <SECRET> -- <command>` runs `<command>`
222
- with only the secrets this pod generation's grant allows — refuses closed, naming the secret, if
223
- the rule does not allow it. `AWS_CONFIG_FILE` is set when the deployment's `pod.volumes` carries a
224
- further projected token beyond the model route's own; read the file it names for what profiles it
225
- configures before assuming the AWS CLI has nothing to reach. Neither variable existing is a
226
- guarantee the read you need is covered — a refusal from either still means what it says — but
227
- neither should be assumed absent without checking.
228
-
229
- ## GitHub PR comment attribution
230
-
231
- Append this exact structured footer to **every** pull-request comment and review that this
232
- phase posts on GitHub. It preserves session provenance on the artifact itself so work stays
233
- attributable to the session that produced it. Dispatch comments carry session provenance
234
- natively through their own `actor`/`origin` fields; this footer is for GitHub PR artifacts and
235
- for the retro's Dispatch message (`skill://legion-retro`):
43
+ | You need a tool the image may not carry, before you install anything | `skill://legion-worker/references/tools.md` |
44
+ | A problem outside your issue, or a failed production check | `skill://legion-worker/references/findings.md` |
236
45
 
237
- ```html
238
- <!-- legion: {"session":"<session-id>","phase":"<phase>"} -->
239
- ```
46
+ ## Every role pushes its own commits
240
47
 
241
- For example:
242
-
243
- ```bash
244
- gh pr comment <pr-number> \
245
- --body $'Verification complete.\n\n<!-- legion: {"session":"<session-id>","phase":"<phase>"} -->' \
246
- --repo <owner>/<repo>
247
- ```
248
-
249
- ## Planner artifact
250
-
251
- The plan lives in `.legion/<issue>/plan.json` and the issue's `plan.md` document, never in the issue's
252
- primary document, which is its spec. Legion sets no rule on whether a plan or spec goes in the
253
- repository: the planner commits a plan, a spec or spec code when the issue, its spec or the
254
- repository asks for it. Otherwise, a skill step that says "save the plan to a file" is satisfied by
255
- the handoff write in the completion gate below.
256
-
257
- A plan that departs from the spec's design records the departure in `plan.md` and in the required
258
- `.legion/<issue>/plan.json` `specDepartures`: `[]` means no departure; otherwise each bounded record names
259
- the spec, plan, evidence and outcome. The planner's role prompt defines that record. The planner
260
- never edits the issue's spec document. Whether the spec changes is the architect's decision
261
- (`skill://legion-architect`, section 1), and the reviewer reads the plan beside the spec.
262
-
263
- ## Implementer push and pull request
264
-
265
- The implementer opens the pull request. After its implementation commit and verification, it
266
- pushes the issue branch under this exact name with the one push procedure every role uses
267
- (*Every role pushes its own commits*, below).
268
-
269
- `jj git push` authenticates as your role's App through the clone's `!legion git-credential`, from
270
- the file your `gh` reads for your issue's repository. Never handle a token.
271
-
272
- Then open the pull request with `gh pr create`. The PR body **must** contain the
273
- line `Dispatch: <KEY>` — the daemon's fallback link from a PR to its Dispatch issue when the
274
- branch name alone is ambiguous. Your pane's `gh` and `git` provide the GitHub
275
- identity; never export, fetch, or replace a token. Other phases advance the existing branch
276
- rather than creating a replacement bookmark or PR.
48
+ - Before a push, read `jj -R "$LEGION_WORKSPACE" log -r 'ancestors(@, 5)'` (earlier phases' commits in it are expected) and run the identity check (`skill://legion-worker/references/default-branch-check.md`). Add no attribution trailer: the pane's jj adds `Omp-Session:`.
49
+ - A push whose commits touch only `.legion/` ends its head's message with `skip-checks: true`, unless it is retro's push (the implementer's retro phase, before the merger's). Retro's push never carries the line, whatever paths it touches, because it is the last push before the merge and a base that requires a check will not merge a head whose checks never ran. No other push carries it. The daemon classifies a push by its paths, never by the trailer, so a wrong trailer can stall the issue but never makes it pass.
50
+ - A planner whose issue moved back from implementing starts on the remote tip, `jj -R "$LEGION_WORKSPACE" new legion/<KEY>@origin`, so its handoff never sits on the implementer's unpushed commits.
277
51
 
278
52
  ## PR body, review, and the merge gate
279
53
 
280
- The implementer writes the pull request body from the template when it opens the pull request,
281
- and every later phase edits its own lines of the live body rather than replacing it. Each proof
282
- (the implementer's `E2E (implementer)` line and `proof` array, the tester's `E2E (tester)` line
283
- and `proof` array) is the changed behaviour exercised on a production-like surface, recorded as
284
- its command or run id, what was observed, the head SHA, and one negative control; a unit test is
285
- never one. **Before you write or edit any line of the PR body or any `proof` array, read
286
- `skill://legion-worker/references/pr-body.md`**: the template, the full definition of a proof,
287
- what the tester verifies, and the simplify pass.
288
-
289
- - **The tester runs the application, not CI again.** It drives the changed surface for real and
290
- tries to break it, judges whether the implementer's tests would catch what it broke, records what
291
- it ran and saw, and must read CI on GitHub for everything static — lint, types and the unit
292
- suites are CI's work, rerun by no tester: `skill://legion-worker/references/pr-body.md`.
293
- - **Review threads** are answered and resolved one by one, never in bulk, and never one you have
294
- not read: one disposition reply per thread, then that thread's own resolution by the
295
- implementer, the pull request's author — its `gh api graphql` mutation after every push that
296
- answers a review, before its completion, for the threads it answered and for the bot threads the
297
- reviewer names to it as accepted (the review App cannot resolve one):
298
- `skill://legion-worker/references/review-threads.md`.
299
- - **No deferrals.** A finding that changes
300
- behaviour, hides an error, or breaks a gate is fixed in this pull request; naming, duplication,
301
- or wording cleanup is batched into the one `Fast-follow:` line instead of iterating per push.
302
- - **The implementer pushes, then completes; it never waits for, watches or polls CI**, and never
303
- sleeps in a loop: `skill://legion-worker/references/pr-body.md` (*Never waiting on CI*).
304
- - **A red CI job** that failed on its own is re-run with
305
- `gh run rerun <run-id> --failed`, never by pushing a new commit or bringing in the base.
306
- - **A conflict or a retarget** is the only reason to bring the base into the branch, always as a
307
- forward merge and never `jj rebase`; the unchanged-diff fingerprint each role compares
308
- afterwards is in the same reference: `skill://legion-worker/references/conflicts-and-rewrites.md`.
309
- - **The merge gate**, in order: the tester's evidence green → the reviewer's approval of the head
310
- → the architect's acceptance → retro → the merger's READY → the merge, which closes the issue →
311
- the implementer's production check, after the close. On READY's acceptance the daemon submits
312
- the merge of the head READY named, unless the answer's note begins `MANUAL_MERGE_REQUIRED:`,
313
- where a person merges it; no role runs `gh pr merge`, and the repository's required reviews and
314
- checks decide when it lands (`skill://legion-worker/references/merge-gate.md`). The reviewer's
315
- submissions, the acceptance, retro's commit, READY, the daemon's submission, and the check follow the same reference.
316
- - **No surface reaches the changed path** is a report to the architect, never a reason to
317
- complete the phase: `skill://legion-worker/references/pr-body.md`.
318
-
319
- ## Completion gate: handoff write, verification, and persistence
320
-
321
- The merger writes no handoff and pushes nothing, so this gate does not apply to it
322
- (`packages/daemon/internal/prompts/roles/merger.md`).
323
-
324
- A planner picking up after the issue moves back from implementing starts fresh on the remote
325
- tip — `jj -R "$LEGION_WORKSPACE" new legion/<KEY>@origin` — since the implementer's unpushed
326
- commits are no longer in the chain (*Every role pushes its own commits*, below).
327
-
328
- Write the handoff, `$LEGION_WORKSPACE/.legion/<issue>/<phase>.json` (`plan`, `implement`, `test`
329
- or `review`), with the ordinary `write` tool: a JSON object with `schemaVersion: 1`,
330
- `phase: "<phase>"`, `issue: "<KEY>"`, `completed: "<RFC 3339 UTC time of writing>"`, and the
331
- phase's own fields exactly as your role prompt spells them — the planner's `requiredSkills`,
332
- `gapAnalysis`, `planReview` and `specDepartures` records; the implementer's `proof` array; the
333
- tester's `implementerProof`, `failures` and, whenever it reports no failure, its own `proof`; the
334
- reviewer's `decision`, counts and `keyFindings`. Nothing stamps the first four for you. Each `proof`
335
- entry, in either phase, is an object of six non-empty strings: `criterion` (the acceptance line it
336
- proves), `surface`, `command`, `observed`, `headSha` (the commit it ran at) and `negativeControl`.
337
- A handoff built from the one already on disk (a test handoff that accumulates review rounds) is
338
- read with `read`, edited, and written whole with `write`, its `completed` set to now.
339
-
340
- Then commit that exact handoff file onto the issue branch:
341
-
342
- ```bash
343
- cd -- "$LEGION_WORKSPACE" && \
344
- jj -R "$LEGION_WORKSPACE" split -m "<phase>: record handoff" .legion/<issue>/<phase>.json
345
- ```
346
-
347
- Then push (below) and report completion: call the `legion` tool with `op: "handoff_complete"` and
348
- `summary` (two sentences for the architect; the tester, and no other role, adds `verdict: "pass"`
349
- or `"fail"`; the merger `ready: true`). **Push before you complete is a hard rule.**
350
- `handoff_complete` finds, with your pane's jj, the newest commit on the issue branch that carries
351
- `.legion/<KEY>/<phase>.json` and reports it to the daemon, and refuses — posting nothing — while:
352
-
353
- - the file has a change still in the working copy: commit it, then complete again;
354
- - the file is missing from the workspace: write it, then commit and push it;
355
- - the file is not committed on this branch (only the base carries it): write and commit it;
356
- - the carrying commit was authored by another App (every role of an issue shares the workspace):
357
- run `jj -R "$LEGION_WORKSPACE" new`, then write and commit this phase's handoff again;
358
- - the carrying commit is not yet on `legion/<KEY>@origin`: push the issue branch, then complete
359
- again.
54
+ - The implementer opens the pull request with the line `Dispatch: <KEY>` in its body, the daemon's link to the issue when the branch name is ambiguous. Later phases push to that branch and edit that pull request, never a new one.
55
+ - **No deferrals.** A finding that changes behaviour, hides an error, or breaks a gate is fixed in this pull request. Only cleanup that changes no behaviour (naming, duplication, wording) may wait, on the body's one `Fast-follow:` line.
56
+ - **The merge gate**, in order: the tester's evidence green → the reviewer's approval of the head → the architect's acceptance → retro → the merger's READY → the merge, which closes the issue → the implementer's production check, after the close. When the daemon accepts READY, it submits the merge of READY's head, unless the answer's note begins `MANUAL_MERGE_REQUIRED:`, where a person merges it; no role runs `gh pr merge`.
57
+ - Append `<!-- legion: {"session":"<session-id>","phase":"<phase>"} -->` to every pull-request comment and review you post: the daemon finds the session behind a review by it.
58
+ - Never write a GitHub issue, by `gh issue` or a non-GET `gh api` on `/issues` (post or edit a PR conversation comment with `gh pr comment`): Legion's issues live on Dispatch. Never run `gh config set` or `gh alias set`, and leave `GH_TOKEN`, `GITHUB_TOKEN` and `GH_HOST` empty: the daemon rewrites your gh directory in place, and a set variable outranks it.
59
+ - Before you report a resource unreachable, check `AGENT_SECRETS_URL` and `AGENT_SECRETS_KEY_DIR` (then `agent-secrets <SECRET> -- <command>`; sjawhar/legion `docs/kubernetes.md`, "Operator configuration") and `AWS_CONFIG_FILE` (read its profiles): a deployment can give your pod either. `agent-secrets` refuses a secret its grant lacks and names it; that refusal is final. Your `task` subagents and background jobs inherit both, and your `gh` and `git`.
360
60
 
361
- Nothing checks the file's shape: the fields your role prompt spells are what the next role reads.
362
- The daemon reads no handoff file and no branch head; it refuses, before recording anything:
363
-
364
- - `HANDOFF_NOT_NEW` — the commit is the one you reported for your previous phase: write and
365
- commit this phase's handoff before completing.
366
- - each `READY_…` refusal of the merger's READY — named, with its remedy, in the merger's role
367
- prompt (`skill://legion-worker/references/merge-gate.md` says how READY is checked).
368
- - `GITHUB_READ_FAILED` — GitHub's failure, not the head's, reading the pull request's head on
369
- GitHub: complete again.
370
-
371
- Such a refusal records nothing, so the corrected call at the same commit is applied. The answer
372
- may carry a `note` (READY published on an already-merged pull request, or the
373
- `MANUAL_MERGE_REQUIRED:` note of a pull request a person merges).
374
-
375
- Retro's last commit removes `.legion/<issue>/` from the head that merges (`skill://legion-retro`);
376
- a round after it, such as one a withdrawn READY sends back, writes and commits its own handoff
377
- again, since `handoff_complete` reports the commit carrying the file. Retro and the merger write no
378
- `.legion/<issue>/<phase>.json`, commit no handoff, and report with `handoff_complete` alone, which
379
- reports the commit the workspace stands on; a look of the production check after the close reports with `handoff_complete` and a `verdict`, and no commit at all.
380
-
381
- **Every role pushes its own commits.** After the handoff commit — and, for the tester, the red
382
- tests it wrote — push the issue branch with the plain `jj` of your pane, from bash in your
383
- workspace; `<KEY>` is your `LEGION_ISSUE`:
384
-
385
- ```bash
386
- cd -- "$LEGION_WORKSPACE" && jj -R "$LEGION_WORKSPACE" bookmark set legion/<KEY> -r @- && jj -R "$LEGION_WORKSPACE" git push --bookmark legion/<KEY>
387
- ```
388
-
389
- A push whose commits touch only `.legion/` (a handoff-only push) ends its head's commit message
390
- with `skip-checks: true` as the last line, preceded by two empty lines, so GitHub starts no
391
- workflow run for it and the daemon carries the code head's verdict to it.
392
- Retro's push never carries the line, whatever paths it touches, because it is the last push before the merge and a base that requires a check will not merge a head whose checks never ran.
393
- Every other push —
394
- code, red tests, `docs/solutions/`, a forward merge, a rewrite — carries no such line. The daemon
395
- classifies a push by the paths its commits touch, never by the trailer: a wrong trailer stalls
396
- the issue and never passes it. Before you write one, read
397
- `skill://legion-worker/references/skip-checks-trailer.md`: the shape GitHub honours, the
398
- `describe` that writes it with trailers off, the bracket keywords banned with it, how a wrong
399
- trailer stalls the issue, and when a pull-request body edit does and does not start a run.
400
-
401
- Before the push, inspect `jj -R "$LEGION_WORKSPACE" log -r 'ancestors(@, 5)'` and run the
402
- identity check above: the chain carries every earlier phase's pushed commits, and pushing them
403
- with yours is expected. Your issue's roles share one clone (under tmux every issue does), so
404
- another role's push moves `legion/<KEY>@origin` here at once, and `jj git push` refuses a remote
405
- branch that moved: report the refusal to the architect with its output, never force. A handoff commit never
406
- sits on an implementer's unpushed chain: when the issue moves back to planning, the implementer's
407
- unpushed commits stay off the bookmark until the implementer returns, and the planner writes its
408
- handoff on the remote tip. The one sanctioned non-fast-forward move is the rewrite of a commit you
409
- already pushed — a `jj squash --into` one, or any other rewrite — and before it, read *Rewriting
410
- pushed commits* in `skill://legion-worker/references/conflicts-and-rewrites.md`: its guard checks
411
- that no other tree's work is built on that commit, and only after it clears is the bookmark moved
412
- with `--allow-backwards`. The merger makes no commit and pushes nothing.
413
-
414
- ## Completion: report to the architect, then stay
415
-
416
- Report completion to the architect: call the `legion` tool with `op: "handoff_complete"` and
417
- `summary`: two sentences for the architect. The tool is your only way to the daemon
418
- (`handoff_complete`; `read_record`, your issue's record, which is what "re-read your issue
419
- record" means; and `request_backward_move`), and nothing of yours runs `legion` from bash. The
420
- tool call is what the extension's phase stall records, and a turn that ends with the phase still
421
- open gets one reminder (two when the first is answered with the tool call written as text again);
422
- do not complete again on a reminder when your first completion was accepted — it stands, and a
423
- second is refused because the issue has already left your phase.
424
-
425
- This publishes your phase's completion to the architect's role and clears the daemon's
426
- record of this issue's active phase. Do not add pipeline labels, run a controller loop, or
427
- invent a different completion protocol — this is the whole contract.
428
-
429
- A reviewer's phase ends with its completion, not with its review; the order of a review round
430
- (the read of the code commit's checks on GitHub; the handoff push; the review of the head that
431
- push made; then the completion) is in `skill://legion-worker/references/merge-gate.md`.
432
-
433
- **A refused completion is information, not a retry loop.** The daemon attributes your report to
434
- the run whose task you took, and answers with what it found. What each answer carries, and what to
435
- do:
436
-
437
- - `HANDOFF_STALE_GENERATION` — names the issue, the run it is on, and the run your completion
438
- reported. The issue has moved to a newer run since your task was given, so the work you just
439
- reported belongs to a run that is over. Nothing you can repeat changes that: stop, push nothing
440
- further, and tell the architect what you completed and that its run has been superseded. A task
441
- for the current run arrives in this same session if the phase still needs you. The same answer
442
- comes when your turn started before the daemon recorded the current run's task as yours, so it
443
- still holds you to the earlier run: that task is sent again. When a task arrives, do what it
444
- asks; if the work it asks for is already committed, call `handoff_complete` again, and never redo
445
- the work or write a second handoff.
446
- - `HANDOFF_NOT_CURRENT_PHASE` — names your role, the issue, and the phase it is in now. The issue
447
- has left your phase; report to the architect rather than completing again.
448
- - `HANDOFF_NO_RUN` — names neither: it says this claim has taken no task, so the daemon cannot
449
- tell which run you are reporting. Your pane is completing outside any assignment. Say so to the
450
- architect; do not re-run the phase. The same answer comes when your turn started before your task
451
- reached you: a notice or a message started it, and the task, refused while that turn ran, is sent
452
- when the turn ends. When a task arrives, do what it asks; if the work it asks for is already
453
- committed, call `handoff_complete` again, and never redo the work or write a second handoff.
454
- - `HANDOFF_ALREADY_RECORDED` — names your role, the phase, the review round and the commit. This
455
- exact call was received before, and its first answer stands: accepted, or a refusal the daemon
456
- records with the call — `HANDOFF_STALE_GENERATION`, `HANDOFF_NOT_CURRENT_PHASE`,
457
- `READY_REQUIRED` or `HANDOFF_NOT_NEW`. `HANDOFF_NO_RUN` is never that first answer, since it is
458
- given before anything is recorded. Sending it again changes nothing; if you did not see that
459
- first answer, tell the architect so and quote this one.
460
-
461
- Quote the answer verbatim in what you tell the architect: with the run and phase it names, the
462
- difference between "my work is lost" and "my work belongs to the previous run" is visible.
463
-
464
- **Stay in this session afterward.** Your process does not exit when your phase completes; it
465
- stays live until your issue leaves the workflow. No move between phases stops it, and only an
466
- explicit stop does: the issue closing; a move to `backlog`, `icebox` or `triage` (a child by a
467
- person or its architect's `park_child`, or the root, which stops the whole tree); a child set back
468
- to `todo` (which stops the interrupted phase's worker, not earlier roles); or an operator stop.
469
- A stop keeps your session, and a crash relaunches it. Your next assignment arrives in this same
470
- session. Other roles on
471
- this issue may reach you through Envoy with
472
- questions about the work you did — answer them, reading `$LEGION_WORKSPACE` and your own
473
- committed handoff as needed, without mutating anything (see Workspace and handoff
474
- precedence above). You will also be the one resumed, with a new prompt in this same
475
- session, if this phase's work needs to run again.
476
-
477
- When blocked on a product, scope, design, lifecycle, or cross-phase decision, `envoy_publish` the
478
- owning architect a concise message: issue, phase, verified observation, what you tried, and the
479
- decision required.
61
+ ## Deployment instructions
480
62
 
481
- Never yield while blocked on a decision someone else owns. Before you stop, make the block visible
482
- where its owner will see it: a product, scope, design, lifecycle, or cross-phase decision goes to
483
- the owning architect as above, and a standalone human to-do goes in `dispatch ask`. Otherwise
484
- proceed: proceeding is the default, and a phase that stops silently holds its issue until someone
485
- notices.
63
+ Deployment instructions in your prompt override this skill where they conflict, except four rules: no deferrals; bringing the base into the branch only on a real conflict or a retarget (`skill://legion-worker/references/conflicts-and-rewrites.md#reintegrating-the-base`); the implementer's own proof on a production-like surface at the head that merges, an applied simplify head included (`skill://legion-worker/references/pr-body.md#what-a-proof-is`, `skill://legion-worker/references/pr-body.md#the-rules-every-phases-evidence-follows`); and the implementer's production check after the close (`skill://legion-worker/references/merge-gate.md#the-production-check-after-the-close`).
@@ -11,8 +11,8 @@ Every path it cites is in sjawhar/legion.
11
11
  merge, never `jj rebase`.**
12
12
  The implementer merges the base into the issue branch only when GitHub reports it `CONFLICTING`, the controller asks
13
13
  because of a conflict, or after the pull request is retargeted to a new base. Otherwise, never reintegrate the base to
14
- pick up the default branch or refresh CI (a single failed CI job is re-run on its own: *A red CI job* in
15
- `skill://legion-worker`). A conflict-forced rebase that leaves the branch's diff unchanged is a
14
+ pick up the default branch or refresh CI (a single failed CI job is re-run on its own: *Never waiting on CI* in
15
+ `skill://legion-worker/references/pr-body.md`). A conflict-forced rebase that leaves the branch's diff unchanged is a
16
16
  confirmation, not a new round (see *The unchanged-diff check* below); that name is the event's,
17
17
  kept by the rules below and the learnings that cite it, and the operation it names is always
18
18
  the merge here. Before merging, record
@@ -35,3 +35,19 @@ never runs.
35
35
 
36
36
  The output must show your role's App in both columns **on every commit you made** — not on the
37
37
  whole list: earlier phases' commits are legitimately authored by their own role's App.
38
+
39
+ ## Which App, and what a wrong one means
40
+
41
+ - Your role's App is the **implement** App for the implementer and the merger, and the **review**
42
+ App for the planner, tester, reviewer and architect; your pane's `JJ_USER` and `JJ_EMAIL` name
43
+ its bot account. A planner's commits authored by the review App are right.
44
+ - Never set `user.name` or `user.email` in any jj or Git scope (`jj config set`, `--config`,
45
+ `git config`): `--config` outranks the pane's identity and puts the wrong App on your commits,
46
+ and the repository-scoped jj config is one file shared by every issue workspace of the clone.
47
+ - A wrong identity on your own commit (the other App, or none) is a pane-environment problem:
48
+ report it to the architect, never pin it (sjawhar/legion
49
+ `docs/solutions/legion/shared-main-repo-hazards-for-concurrent-issue-workspaces.md`, Hazard 1).
50
+ - Another role's commit with you as committer, which you did not rewrite under the guard in
51
+ *Rewriting pushed commits* (`skill://legion-worker/references/conflicts-and-rewrites.md`), means
52
+ something rewrote commits it should not have: stop and send the architect this log. A forward
53
+ merge rewrites nothing, so it changes no committer.
@@ -13,8 +13,8 @@ whether it needs an issue, where, and whether Legion works it.
13
13
  - A problem inside your issue is not such a finding: fix it in your change, since nothing needed
14
14
  for correctness is deferred.
15
15
  - A problem inside your tree is work its root spec's acceptance needs. A phase worker's such
16
- problem outside its own issue goes to the tree's architect (`skill://legion-worker`, the
17
- escalation paragraph), which may file it as a child of the tree. Anything else, in the same
16
+ problem outside its own issue goes to the tree's architect (`skill://legion-worker`, *Stop
17
+ rules*), which may file it as a child of the tree. Anything else, in the same
18
18
  repository or not, is a finding.
19
19
  - Search first (`skill://dispatch-first`): when an open issue already tracks the problem, comment
20
20
  the evidence on that issue and ask nothing. When an open ask on the report issue already asks
@@ -57,7 +57,7 @@ Under the Go daemon a check or workflow the base branch requires that settles re
57
57
  before the completion or after it, sends the work back to `implementing` with the failing checks
58
58
  named, until `max_fix_attempts` is spent, when the architect decides. The one CI result an implementer waits for is a re-run: when its task names a red that
59
59
  failed on its own, it re-runs the failed jobs once (`gh run rerun <run-id> --failed`) and completes once
60
- the re-run settles green, woken by the pull request's checks event (`skill://envoy`, *Waiting for
60
+ the re-run settles green, woken by the pull request's checks event (`skill://envoy`, *Wait for
61
61
  CI or a merge*: subscribe, then end the turn), never by a sleep loop. A completion while that red
62
62
  still stands is sent back, at once for a required check and at the daemon's next read of the runs
63
63
  (within two minutes) for a required workflow.
@@ -45,7 +45,7 @@ Three facts govern every thread, whoever opened it.
45
45
  Reply on each thread you answer, then tell the implementer the node ids of exactly the threads
46
46
  you accepted — a bot's findings you adjudicated — never one you have not read: an
47
47
  `envoy_publish` to the implementer's role topic (it is live on the issue and answers while you
48
- wait; `skill://legion-worker` "Asking another role" has the topic), or your review body, which
48
+ wait; its topic is yours from the `Legion addressing` line with `-implementer` as the last part), or your review body, which
49
49
  it reads at its next round. The implementer resolves exactly those with its own `gh`. GitHub
50
50
  cannot tell a CI bot from a person whose `gh` is routed to an App, so such a thread may be a
51
51
  person's finding: accept it only when the finding itself is settled (a genuine Minor is settled