@sjawhar/opencode-legion-envoy 8.16.0 → 8.17.1

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.
@@ -1,121 +1,56 @@
1
1
  ---
2
2
  name: dispatch-brainstorming
3
- description: "Use in a session with Dispatch whenever a design conversation with a person starts: brainstorming or /brainstorming, \"let's design\", writing or changing a spec, writing an implementation plan, or a feature request or change that needs a person's choices. In a session with Dispatch it replaces superpowers' brainstorming and writing-plans; a Legion architect's own spec follows skill://legion-architect instead."
3
+ description: "Use when a session with Dispatch starts a design conversation with a person: brainstorming, /brainstorming or \"let's design\". Also use it there for a spec, an implementation plan, or a change that needs a person's choices. It replaces superpowers' brainstorming and writing-plans. A Legion architect's own spec follows skill://legion-architect instead."
4
4
  ---
5
5
 
6
6
  # Brainstorming in Dispatch
7
7
 
8
- This skill governs a design conversation with a person, never a Legion architect's own issue
9
- spec: an architect follows `skill://legion-architect` for that, even for a child issue.
8
+ A Legion architect's own issue spec, a child's too, follows `skill://legion-architect`. A Legion phase worker never writes the spec: it sends the decision to its architect (`skill://legion-worker`).
10
9
 
11
- In a session with Dispatch, such a conversation happens in its issue's spec, and the plan that
12
- follows is a document on the same issue. This skill replaces superpowers' `brainstorming` and
13
- `writing-plans` there, even when the user invokes one of them by name:
10
+ This skill replaces superpowers' `brainstorming` and `writing-plans`, even when the user names one:
14
11
 
15
- - No design question goes to chat. Every question is a decision block in the spec, and your reply
16
- in chat links the issue and asks nothing.
17
- - There is no limit of one question per message. Every question that is ready goes out at once.
18
- - There is no approval after each section, only the one at the end.
19
- - A small change gets a short spec, never a design in chat: its size shortens the spec and changes
20
- nothing about where the conversation happens.
21
- - The spec is the issue's primary document and the plan is its `plan.md` document, in place of
22
- superpowers' spec and plan files (`docs/superpowers/specs/`, `docs/superpowers/plans/`). A copy
23
- also goes in the repository only when the person, the issue, its spec or the repository asks for
24
- one.
12
+ - The spec is the issue's primary document, the plan its `plan.md`. No `docs/superpowers/` files.
13
+ - Each design question is a decision block in the spec, never a chat question. A small change gets a short spec.
14
+ - Send every ready question at once. Request approval once, at the end.
15
+ - Ask in stages: clarifying questions, two or three approaches with a recommendation, the design by section. A question that depends on no open answer goes out at once.
16
+ - Copy the spec, plan or spec code into the repository only when the person, the issue, its spec or the repository asks.
25
17
 
26
- The brainstorming stages still shape what you ask: clarifying questions, then two or three
27
- approaches with a recommendation, then the design section by section. A question that depends on
28
- no open answer goes out at once, whatever its stage.
29
-
30
- Read `skill://dispatch` before the first version: its "Writing a spec", "Decision blocks",
31
- "Writing for the human" and "Approval of a spec" sections define the spec's shape, each block's
32
- shape, and when approval is requested. A Legion phase worker never writes the issue's spec
33
- document; it sends a decision to its architect (`skill://legion-worker`).
18
+ Before the first version, read the code and documents the design touches. Before the first version, also read the `skill://dispatch` sections "Writing a spec", "Decision blocks", "Writing for the human" and "Approval of a spec".
34
19
 
35
20
  ## Where the spec lives
36
21
 
37
- Search Dispatch first, as `skill://dispatch-first` says. When an issue already tracks the work, its
38
- primary document is the spec: extend it in place with `dispatch doc-edit`, keeping the human's own
39
- text. Otherwise create the issue with its first version as `spec`, in the project a search hit
40
- already named or, when none does, the project the human names:
41
-
42
- ```bash
43
- dispatch issue --project <KEY> --title '<title>' --spec-file - <<'EOF'
44
- <the spec's first version>
45
- EOF
46
- ```
47
-
48
- No command lists every project, so when nothing you found names one, ask the human in chat which
49
- project the issue belongs in before you create it — a filing question with nowhere else to land
50
- yet, not a design question, so it does not change "your reply in chat links the issue and asks
51
- nothing" for the design itself. Never read the project from the environment, a configuration file,
52
- or the Dispatch HTTP API: every read and write goes through a `dispatch` command.
53
-
54
- Before the first version, read the code and documents the design touches, so the facts you write
55
- are ones you checked.
22
+ 1. Search first (`skill://dispatch-first`). If an issue tracks the work, extend its primary document with `dispatch doc-edit`, keeping the human's text.
23
+ 2. Else run `dispatch issue --project <KEY> --title '<title>' --spec-file -` in the project a search hit names.
24
+ 3. If no hit names a project, ask the human in chat which one (`dispatch projects` lists them). This is a filing question, not a design question.
25
+ 4. Use only `dispatch` commands. Never get the project from the environment, a configuration file or the Dispatch HTTP API.
56
26
 
57
27
  ## Each turn
58
28
 
59
- 1. **Start with what is established.** The first version holds only what the conversation has
60
- established: the problem and its evidence, what the human has said in their own words, the
61
- facts the next questions need, and each question that is ready, as a decision block at the end
62
- of the section that sets it up. Write nothing past those questions: no design, no defaults you
63
- chose, no "what we will build", and no recommendation outside a decision block's own text. A
64
- point the human has not stated, however obvious it seems (what a word in the request means, how
65
- an edge case behaves, what a change does to an existing command), goes inside a decision block
66
- or stays out. This is stricter than `skill://dispatch`'s general rule for an inferred point
67
- elsewhere in a spec ("a point you inferred says so, with the reasoning"): in a live conversation
68
- nothing is settled until the human has seen it, so even a flagged inference waits for its own
69
- decision block.
70
- 2. **The human answers or comments.** Reply to each human comment in its thread
71
- (`dispatch comment --reply-to <comment id>`), then rewrite the passage the answer or the comment
72
- changes. Under an open ask whose next move is yours, such as the approval request you must
73
- revise or hand back, reply with `--reply-to-ask <ask id> --turn agent` instead: a `--reply-to`
74
- reply takes the default turn, which hands the request back to the human unchanged, and a call
75
- with a corrected `--summary` is refused while it waits on them.
76
- 3. **Each next version keeps answers in place and adds what they open.** An answered decision
77
- block already carries its own record, as `skill://dispatch`'s "Writing a spec" says; leave it
78
- where it is. Where an answer changes design text elsewhere in the spec, rewrite that text. Then
79
- add the next sections, each with its question. Every question that is ready goes out
80
- at once, each as a decision block at the end of the section that sets it up; a question waits
81
- only when it depends on an answer still open.
82
- 4. **A comment that answers a question settles it** as surely as the block does. It carries no
83
- rendered record, so write it into the text at once, recording the person as `skill://dispatch`'s
84
- "Writing a spec" says, and close the block with `dispatch resolve-ask` if the human has not.
85
- 5. **Request approval at the end, not after each section.** Once nothing in the spec is new to the
86
- human, request it exactly when "Approval of a spec" in `skill://dispatch` says: every decision
87
- block settled, the human has agreed to every point in the spec, and the current
88
- version is not yet approved (or waived, as that section's next paragraph covers). The request
89
- carries nothing new, as that section also says.
29
+ 1. **First version: only what the human settled.** Write the problem, its evidence, the human's words and the facts the questions need. Add each ready question as a block at the end of its section. Write no design, no default you chose, and no recommendation outside a block. A point the human did not state goes in a block or stays out, however obvious. A flagged inference waits too.
30
+ 2. **Reply to each comment in its thread** (`dispatch comment --reply-to <comment id>`), then rewrite what it changes. When the next move on an open ask is yours, such as an approval request to revise, use `--reply-to-ask <ask id> --turn agent`.
31
+ 3. **Each next version keeps answered blocks in place** and rewrites every passage a decision changes. The spec records the current design and requirements, never how you got there. Then add the next sections and their ready questions.
32
+ 4. **A comment that answers a question settles it.** Write the answer into the text at once, as "Writing a spec" says. Close the block with `dispatch resolve-ask` if it is still open.
33
+ 5. **Request approval** when nothing in the spec is new to the human, as "Approval of a spec" says.
90
34
 
91
35
  ## Coming to terms
92
36
 
93
- The conversation comes to terms in both directions. Explain what the code does today, plainly
94
- enough for the human to react to and with each tool, event and route it uses named exactly (as
95
- "Writing for the human" in `skill://dispatch` says), and ask; the human's model comes out of those
96
- reactions, and so do corrections to it. Neither your model nor theirs is the starting truth.
37
+ Explain plainly what the code does now, naming each tool, event and route exactly, and ask. Neither model is true at the start: the human's reactions give their model and its corrections.
97
38
 
98
- ## The plan
99
-
100
- Once the spec is approved — or, when the issue needed no spec at all (a bug fix with no design
101
- decision), once you have enough to plan from — the implementation plan is the issue's `plan.md`
102
- document, never its spec:
39
+ ## Handing over a spec or plan
103
40
 
104
- ```bash
105
- dispatch artifact --issue <KEY> --name plan.md --content-file - <<'EOF'
106
- <the plan>
107
- EOF
108
- ```
41
+ 1. Start your chat reply with:
42
+ 1. Each decision the human must make: options, trade-offs and your recommendation, clear without the document. The human answers in the block.
43
+ 2. Each point the human has not yet settled, one line each, with a line reference.
44
+ 3. The link.
45
+ 2. The reply carries only what is new. The document stays the full current design.
46
+ 3. If no decision is open and nothing is new, do not ask for review in the reply. Say the document records what you agreed. Turn step 5 still applies.
47
+ 4. When you ask for review, say "ready for review", never "complete". Put the uncertainty first and show your reasoning.
109
48
 
110
- Uploading `plan.md` again writes its next version. `writing-plans`'s content rules still apply in
111
- full — file structure, task right-sizing, bite-sized steps, no placeholders, the header, and its
112
- self-review — only where the plan lives changes: the issue's `plan.md`, in place of a plan file.
113
- A copy in the repository, or spec code there, goes in only when the person, the issue, its spec or
114
- the repository asks for it.
115
- Technical choices inside the approved design are made in the plan and need no question. A plan
116
- never changes a decision the human made in the spec: a change to one goes back to the spec as a
117
- decision block, with the evidence for it.
49
+ ## The plan
118
50
 
119
- Execution reads the plan the same way: `dispatch doc-read --issue <KEY> --artifact plan.md` in place
120
- of opening a plan file, then follows `executing-plans` or `subagent-driven-development` as it would
121
- for a file on disk.
51
+ - Write it after the spec's approval. With no spec (a bug fix with no design decision), write it when you can plan.
52
+ - Upload it with `dispatch artifact --issue <KEY> --name plan.md --content-file -`. Each upload is a new version.
53
+ - Follow all `writing-plans` content rules: file structure, task size, small steps, no placeholders, the header, its self-review.
54
+ - Make technical choices inside the approved design in the plan, with no question. A change to a human's decision goes back to the spec as a block, with its evidence.
55
+ - If the human says "plan only", stop after the plan.
56
+ - To execute, read it with `dispatch doc-read --issue <KEY> --artifact plan.md`, then follow `executing-plans` or `subagent-driven-development`.
@@ -1,58 +1,40 @@
1
1
  ---
2
2
  name: dispatch-first
3
- description: "Use in any session with the dispatch command, before planning, filing an issue, asking a human, posting a finding, or starting work that someone may already track or have decided."
3
+ description: "Use when a session has the dispatch command, before you plan, file an issue, ask a human, post a finding, or start work. Someone may track that work already or hold a decision on it."
4
4
  ---
5
5
 
6
6
  # Dispatch first
7
7
 
8
- Dispatch already holds most of what you are about to plan, file or ask: the open issues, their
9
- specs, and the answers humans gave. A second issue for tracked work, or a question a human already
10
- answered, costs that human the time to notice it and splits the history across two places.
8
+ Dispatch holds the open issues, their specs and the answers humans gave. A duplicate issue or a repeated question costs a human time and splits the history.
11
9
 
12
10
  ## Search before you act
13
11
 
14
- Before you plan, file an issue, ask, post a finding or start work, search Dispatch with the `dispatch` command in your shell (`dispatch --help` lists every command). Every word of
15
- the query must match, so each word you add can only lose hits: search with two or three words, the
16
- thing and what is wrong with it, as a user would name them. Never paste a draft.
12
+ - Before you plan, file an issue, ask, post a finding or start work, run `dispatch search` (`dispatch --help` lists every command).
13
+ - Every query word must match, so each added word can only lose hits. Use two or three words: the thing and what is wrong with it, as a user names them. Never paste a draft.
17
14
 
18
15
  ```bash
19
16
  dispatch search --query 'broadcast send order'
20
17
  dispatch search --query 'reviewer threads OR review comments'
21
18
  ```
22
19
 
23
- When a query finds nothing, drop a word before you add one. Try two or three wordings (the
24
- component's name, the symptom, the fix) before you conclude that nothing exists. Open every hit
25
- that could be yours with `dispatch read`, then its parent (the `child_of` row under `Links:`); the
26
- parent's children and the issue's `Components:` line show where the rest of that work lives.
20
+ - No hits: drop a word before you add one. Try two or three wordings (the component's name, the symptom, the fix) before you conclude that nothing exists.
21
+ - Open each hit that could be yours with `dispatch read`, then its parent (the `child_of` row under `Links:`). The parent's children and the `Components:` line show where the rest of the work is.
27
22
 
28
23
  ## What to do with what you find
29
24
 
30
- Filing an issue or opening an ask also searches for you: the result's `advice.suggestions` names
31
- likely duplicates or a decision that may already settle it. Treat a hit there the same as one you
32
- found yourself.
33
-
34
- - **The work is already tracked: extend that issue.** Put the finding on it (a comment, a message,
35
- or an edit to its spec) instead of filing another. File a new issue only when no hit covers the
36
- work, and cite the nearest one you ruled out (`dispatch://KEY`).
37
- - **The question is already decided: cite the decision.** An answered ask is the record. Point to
38
- it where you rely on it (`dispatch://KEY/ask/<id>`) instead of asking again.
39
- - **You met a duplicate: close it.** Keep the issue that holds the spec and the discussion, carry
40
- over anything only the duplicate has, then close the duplicate with a reason that names the
41
- survivor: `dispatch issue-update --issue <KEY> --status done --reason 'Duplicate of dispatch://KEY.'`.
42
- When the duplicate carries the `legion` label, or another session or a human holds its claim,
43
- comment on it naming the survivor instead of closing it.
44
- - **Every ask and message stands on its own.** The person who answers sees only that text: put the
45
- facts, the options and your recommendation in it, and link what you cite (`dispatch://…`)
46
- instead of writing "see above" or "my earlier message".
25
+ `dispatch issue` and `dispatch ask` also search: treat a hit in the result's `advice.suggestions` as one you found.
26
+
27
+ - **Work already tracked:** put the finding on that issue (a comment, a message, or a spec edit). File a new issue only when no hit covers the work, and cite the nearest one you ruled out (`dispatch://KEY`).
28
+ - **Question already decided:** the answered ask is the record. Cite it (`dispatch://KEY/ask/<id>`) where you rely on it. Do not ask again.
29
+ - **Duplicate found:** keep the issue with the spec and the discussion, and copy over what only the duplicate has. Then close it: `dispatch issue-update --issue <KEY> --status done --reason 'Duplicate of dispatch://KEY.'`. If it has the `legion` label, or another session or a human holds its claim, comment on it with the survivor's name. Do not close it.
30
+ - **Every ask and message stands alone:** the reader sees only that text. Put the facts, the options and your recommendation in it. Link what you cite (`dispatch://…`). Never write "see above" or "my earlier message".
47
31
 
48
32
  ## Design in the spec
49
33
 
50
- A design conversation with a person, or the implementation plan that follows one, uses
51
- `skill://dispatch-brainstorming`: read it before your first design question on a change, the spec,
52
- or that plan. It replaces superpowers' `brainstorming` and `writing-plans` here, even when the user
53
- invokes one by name. Before a spec's first version and each approval request, have a fresh read-only subagent (on Oh My Pi, `task(agent="scout")`, or whatever read-only agent the host bundles) check it against the code, the human's words and any command output a claim rests on, and resolve what it flags. A Legion architect's own issue spec follows `skill://legion-architect`, and its fresh reader in that Legion session is the Legion plugin's `plan-gap-analyst` agent.
34
+ - A design conversation with a person, or the plan that follows it, uses `skill://dispatch-brainstorming`. Read it before your first design question, the spec, or the plan. It replaces superpowers' `brainstorming` and `writing-plans` here, also when the user names one of them.
35
+ - Before a spec's first version and each approval request, get a fresh read-only subagent to check it. On Oh My Pi, use `task(agent="scout")`. Elsewhere, use the host's read-only agent. It checks the spec against the code, the human's words and the command output that its claims rest on. Resolve what it flags.
36
+ - A Legion architect's own issue spec follows `skill://legion-architect`. Its fresh reader in that Legion session is the Legion plugin's `plan-gap-analyst` agent.
54
37
 
55
38
  ## Load the full skill before you write
56
39
 
57
- Before any write to Dispatch (an ask, a message, a comment, a document edit, a status change, a
58
- claim), load `skill://dispatch` unless you already have in this session.
40
+ Before any write to Dispatch, load `skill://dispatch`: an ask, a message, a comment, a document edit, a status change, a claim. Skip this if you loaded it in this session.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: legion-architect
3
- description: Own a Legion root or child issue through event-driven decomposition, waves, gates, integration, retro, sign-off, and close.
3
+ description: Own a Legion root or child issue through event-driven decomposition, waves, gates, integration, acceptance, retro, and the merge that closes it.
4
4
  ---
5
5
 
6
6
  # Legion Architect
@@ -15,8 +15,9 @@ separate coordinator to finish necessary work.
15
15
  - Use the `legion` tool for lifecycle writes. Its issue key is the Dispatch key
16
16
  (pattern `^[A-Z][A-Z0-9]*-[0-9]+$`, e.g. `LEGION-41`).
17
17
  - The daemon starts every Legion role itself and sequences each issue's phases from its fixed
18
- workflow table: planner, implementer, tester, reviewer, retro (the implementer again), merger,
19
- and, after the pull request merges, the implementer's production check. One role works an
18
+ workflow table: planner, implementer, tester, reviewer, your acceptance (`accepting`, where no
19
+ worker runs), retro (the implementer again), merger, and the merge, which closes the issue; the
20
+ implementer's production check follows the close. One role works an
20
21
  issue at a time, and the handoff or event that ends its phase is what starts the next; you start,
21
22
  re-assign and order no worker. Message a known phase worker with `envoy_publish` to
22
23
  `notifications.role.` followed by its encoded role token. Phase workers escalate lifecycle,
@@ -221,7 +222,7 @@ reachable, do not have a different running session perform the read on this tree
221
222
  fold the result into the spec as if it were routine: write the missing capability as its own
222
223
  decision block — which external system, which read or write, why the spec needs it — addressed
223
224
  to the human, in the same spirit as the implementer's ask to a person when the deployment
224
- instructions name nobody for a deploy (section 6), and leave it
225
+ instructions name nobody for a deploy (`skill://legion-worker/references/merge-gate.md`), and leave it
225
226
  open until the human resolves it. A workaround substituted for that record only hides the gap
226
227
  from the next tree that hits it.
227
228
 
@@ -250,12 +251,13 @@ stays out of the workflow.
250
251
  No notice marks the last child's close as the end-game: each closure arrives as its own
251
252
  `child-closed`, and none is a reason to close the parent. Today's daemon does not order the root's
252
253
  own phases after its children: when the design gate opens it starts every admitted issue of the
253
- tree, the root included, so the root's tester can run, and its pull request merge, before any
254
- child merges. To get parent integration evidence against the repository's default branch your
255
- addressing line names after the last child merges, file the parent's integration check as a final
256
- child whose acceptance is every parent criterion proven on that default branch, release it with
257
- `release_children` only once every other
258
- child has closed, and sign off the root only after it closes. This holds until the redesign's
254
+ tree, the root included, so the root's tester and reviewer can run, and the root reach `accepting`,
255
+ before any child merges; your acceptance is where the root waits for its children (section 7). To
256
+ get parent integration evidence against the repository's default branch your addressing line names
257
+ after the last child merges, file the parent's integration check as a final child whose acceptance
258
+ is every parent criterion proven on that default branch, release it with `release_children` only
259
+ once every other child has closed, and accept the root (section 6) only after it closes. This holds
260
+ until the redesign's
259
261
  integrating phase ships (dispatch://LEGION-223). When that check's tester fails, the daemon sends
260
262
  the child back to its implementer; a failure whose fix belongs in other work becomes a new
261
263
  corrective child wave you create and release, and the tree returns to children-in-flight. Do not
@@ -268,9 +270,10 @@ registering its spec or asking for approval again. A child whose old root had no
268
270
  none, and its catch-up says `handed_over` without `carried`. Its workers already run their phases,
269
271
  so its architect decomposes nothing. It reads the root's phase from the catch-up (for a root
270
272
  `held`, the phase its `held` notice names). Before `awaiting_merge` it registers its spec, the gate
271
- its READY waits for, and starts nothing on that gate's `design-approved`; in `awaiting_merge` or
272
- `production_check` the READY is already through, so it registers no spec, asks no human to approve
273
- one, and signs off after the production check. `awaiting_merge` can move back: a red or
273
+ its READY waits for, and starts nothing on that gate's `design-approved`; a child carried in
274
+ `accepting` is yours to accept (section 6). In `awaiting_merge` the READY is already through, so it
275
+ registers no spec and asks no human to approve one: the merge closes the issue, and the production
276
+ check after it is the implementer's. `awaiting_merge` can move back: a red or
274
277
  conflicting head returns the root to `implementing` and its next READY reads the gate again, so if
275
278
  a later `ready-refused` arrives because the head was sent back, it registers then, as that row
276
279
  says. The child stays its own tree after hand-over; reopening the old root later does not take it
@@ -286,8 +289,8 @@ child wave; a passing result goes on to review and the merge-gate sequence by th
286
289
 
287
290
  ## 5. Retro
288
291
 
289
- Retro is mandatory for every issue that passed review, before merge, and the daemon runs it: when
290
- the reviewer's approval ends the review round, it moves the issue to `retro` and starts the
292
+ Retro is mandatory for every issue that passed review, before the merge, and the daemon runs it:
293
+ when your `sign_off` accepts the issue (section 6), it moves the issue to `retro` and starts the
291
294
  implementer on it, in the same agent's session, which stayed live after its phase ended (every
292
295
  started role stays live until its issue closes). You start nothing for it. Never `envoy_publish` to
293
296
  the implementer's role topic to start retro: the daemon's start is what records which role owns
@@ -303,18 +306,41 @@ came back empty, or that GitHub refused the body, it has pushed nothing and is s
303
306
  Answer it with `envoy_publish` to its role topic, saying how from the deployment instructions;
304
307
  when they do not say, open a `dispatch ask` naming the missing instruction.
305
308
 
306
- ## 6. Architect sign-off and merge
309
+ ## 6. Acceptance and the merge
307
310
 
308
- Sign off only when scope is fully met, integration evidence is current, corrective work
309
- is complete, review is clean, retro completed, and no necessary work was silently
310
- deferred. Make the sign-off comment explicit about that evidence. Sign-off also requires the
311
- implementer's production report: a `Production:` line that names what was driven, how, what was
312
- observed, and the merge commit — never a `pending` one, and never a staging pass.
311
+ The reviewer's approval of the head moves the issue to `accepting` (its Dispatch status stays
312
+ `needs_review`), where no worker runs and the acceptance is yours; the reviewer's `phase-finished`
313
+ notice with an `APPROVED` review is the cue. Read the evidence against every acceptance line of the
314
+ spec and the plan: the tester's handoff (`.legion/<issue>/test.json` at the approved head), the PR
315
+ body's `E2E (implementer)` and `E2E (tester)` lines, the reviewer's approval of that head by SHA
316
+ (`gh api repos/<o>/<r>/pulls/<n>/reviews`), and, for a parent, that every child is `done`
317
+ (section 3). Accept only when scope is fully met, integration evidence is current, corrective work
318
+ is complete, review is clean, and no necessary work was silently deferred. Post the acceptance as a
319
+ `dispatch comment` explicit about that evidence, then accept with `sign_off`, which runs only in
320
+ `accepting` (refused `SIGNOFF_OUTSIDE_ACCEPTING` elsewhere) and moves the issue to `retro` with the
321
+ status `retro`:
322
+
323
+ ```text
324
+ dispatch comment --issue LEGION-40 --body-file - <<'EOF'
325
+ <acceptance: scope, integration evidence, the tester's handoff, both E2E lines, the approved head>
326
+ EOF
327
+ legion({ op: "sign_off", issue: "LEGION-40" })
328
+ ```
329
+
330
+ What fails goes back, not forward: `request_backward_move` with `issue` (your grant serves the
331
+ tree, so the move names the issue), `to` `implementing` or `testing`, and a `reason` naming what
332
+ fails; the daemon starts that phase's role with the reason in its task and counts a review round,
333
+ as a reviewer's request for changes does. A `handoff_complete` from you in `accepting` is refused
334
+ (`ACCEPTANCE_IS_SIGN_OFF`). CI red at the head in `accepting` returns the issue to `implementing`
335
+ by the daemon's table, as in review. No `Production:` line is asked here: the production check is
336
+ the implementer's after the merge closes the issue (section 7), and nothing after the merge is
337
+ yours.
313
338
 
314
339
  The daemon keeps this order from its fixed table; you start none of its steps:
315
340
 
316
341
  1. tester green and review cycles complete;
317
342
  2. on a clean review, the reviewer approves the head by SHA, and the daemon moves the issue to
343
+ `accepting`, where you accept it with `sign_off` or send it back; your `sign_off` moves it to
318
344
  `retro`. The approved head still carries the issue's handoffs, `.legion/<issue>/`;
319
345
  3. retro commits its learnings under `docs/solutions/` on top of the approved head, then, as the
320
346
  one final commit, the removal of `.legion/<issue>/`, so no merge carries a handoff onto the
@@ -341,17 +367,10 @@ The daemon keeps this order from its fixed table; you start none of its steps:
341
367
  back to `reviewing`, the move's reason naming the code and what it found, so the reviewer runs a
342
368
  new round. A READY refused because the head still carries `.legion/<issue>/` goes back to
343
369
  `retro`, so the implementer's retro removes it.
344
- 5. the merge lands under the repository's rules; the daemon then starts the **implementer** once
345
- more, on the production check.
346
- It drives the changed path in production through the user's own access path and records
347
- what it saw on the pull request and on this issue. Sign off only after the implementer's production
348
- report exists. A defect it finds is a corrective child issue of this tree, not a note on a
349
- closed one. If the implementer cannot perform the deploy itself, it asks the agent or role the
350
- deployment instructions name for that deploy (an Envoy role), gives it the merge commit, and
351
- waits on the production signal the instructions name; the issue waits with it. It opens a
352
- `dispatch ask` to a person only when the instructions name nobody for that deploy, starting
353
- with the production gap and why it matters, then naming the required step, its risk, and
354
- outcome-named options. No one is ever asked for approval to deploy.
370
+ 5. the merge lands under the repository's rules and closes the issue (section 7). The implementer's
371
+ production check follows the close, in its own session and on the pull request; you are asked
372
+ nothing for it, and a defect it finds is filed as an issue of its own in the project, never as a
373
+ child of the closed one.
355
374
 
356
375
  What returns the tree to review: a changed diff — a commit above the approved head that
357
376
  touches anything outside `docs/solutions/` and the issue's `.legion/<issue>/`, or a
@@ -366,13 +385,14 @@ never a rebase, since a rebase rewrites every descendant of the chain's fork poi
366
385
  another tree's branch stacked on it), pushes it as every role pushes (`jj git push`; a genuine
367
386
  fast-forward, and a code push, so no `skip-checks: true` line), and posts the before/after fingerprints; the tester re-runs the bare gates only;
368
387
  the reviewer confirms and approves the new head by SHA (or continues its round if it had not
369
- approved); the daemon carries the issue on through retro to the merger, whose new READY packet the daemon posts.
388
+ approved); the daemon carries the issue on through your acceptance and retro to the merger, whose new READY packet the daemon posts.
370
389
  This merge happens only when GitHub reports `CONFLICTING`
371
390
  (`gh pr view <n> --json mergeable,mergeStateStatus`); read that on every end-game
372
391
  wake — `phase-finished`, `catch-up`, `checks-red`, `review-stuck` — because a `CONFLICTING`
373
392
  PR gets no CI and no wake announces it. The moment you see it, tell the worker holding the issue's
374
393
  phase (`envoy_publish` to its role topic) to move the issue back to `implementing` with
375
- `request_backward_move`; in `awaiting_merge`, where no worker holds a phase, open a `dispatch ask`
394
+ `request_backward_move`; in `accepting` the move is yours (`request_backward_move` with `issue`);
395
+ in `awaiting_merge`, where no worker holds a phase, open a `dispatch ask`
376
396
  naming the conflict for the human who merges. Do not let the merger send a READY packet for an
377
397
  obsolete approval.
378
398
 
@@ -387,18 +407,24 @@ role topic, or its review body); the reviewer resolves none.
387
407
 
388
408
  ## 7. Close
389
409
 
390
- After the merge result and the implementer's production report are recorded, post the sign-off and
391
- close this issue with `sign_off`, which writes `done`:
392
-
393
- ```text
394
- dispatch comment --issue LEGION-40 --body-file - <<'EOF'
395
- <sign-off: scope, integration evidence, review, retro, merge, and the implementer's production report>
396
- EOF
397
- legion({ op: "sign_off", issue: "LEGION-40" })
398
- ```
399
-
400
- Closing a child supplies the closure event (`child-closed`) to its parent. Do not close a parent
401
- until the entire end-game sequence has completed.
410
+ The merge closes the issue: when GitHub reports the pull request merged while the issue is in
411
+ `awaiting_merge` (a merge before that closes it the moment it gets there), the daemon writes
412
+ `done`. A child's close reaches you as `child-closed`; the daemon retires five of its six claims,
413
+ suspends its implementer with its session kept, and sets its Sandbox `Suspended` with its volume,
414
+ because the implementer still owes the production check: handed to it in its live session at the
415
+ merge, it is work after the close that holds no pod while it waits for the deploy
416
+ (`skill://legion-worker/references/merge-gate.md`, *The production check after the close*). A
417
+ root's close writes `done`, frees the tree's admission slot, and lingers the tree for
418
+ `linger_hours` with every member suspended; a child still in the workflow at the end of the linger
419
+ is handed over (section 3), and the tree's close waits for a member's open check.
420
+
421
+ Nothing of the check is yours: you post no sign-off after the merge and wait for no record. Its
422
+ record lives on the pull request alone, since Dispatch refuses a write on a closed issue; a defect
423
+ it finds is filed as an issue of its own in the project, never a child of the closed one; and
424
+ `read_record` shows a closed issue's open check (`check`: the pull request, the merge commit, the
425
+ looks, what woke the last one and when the next is due). A parent waits in `accepting` until
426
+ every child is `done` (section 3): accepted earlier it would merge before its children, the state
427
+ dispatch://LEGION-703 has the daemon rule out.
402
428
 
403
429
  ## Wake routing
404
430
 
@@ -418,13 +444,13 @@ active phase worker.
418
444
  | `child-not-recorded` | Its `reason` names a child your tree did not record and why: its repository resolves to none (neither it nor an ancestor names one, and the project has no default), or to one not mapped to the project, or to one the daemon leaves out for a missing GitHub App. The daemon said why on the child too. Set the child's repository to one of the project's (`dispatch issue-update --repo owner/name`), then release it again with `release_children`; tell the controller when the repository it needs is not served. |
419
445
  | `design-approved` | Its `version` is the approved one. A human approved the root spec document at its current version; the gate is open. Proceed to section 2 — except on a root whose catch-up said `handed_over`: its workers already run their phases, so start nothing; the approval releases any READY the gate refused. One whose `version` is the version a human's own answer to a decision block wrote, after an earlier approval (Dispatch carried that approval to it, section 1), opens nothing new: carry on, and release no wave because of it. |
420
446
  | `design-changes-requested` | Its `version` and `reason`. A human asked for changes to the root spec at `version`, for `reason`. Revise the spec as the reason asks and request approval again as section 1 says; stay parked; the gate is closed. |
421
- | `phase-finished` | The daemon has already moved the issue to its next phase by its fixed table and started that phase's role; you start nothing. Read the committed handoff for the finishing phase; if it shows unresolved gaps, tell the role now working the issue (`envoy_publish` to its role topic). A `planner` notice that names a departure from the spec's design defers to section 1's full condition: when the approved Summary, Acceptance, scope and settled decisions still hold, the plan is the record; otherwise change the root spec and request approval again as section 1 says. A `reviewer` notice whose GitHub review is `CHANGES_REQUESTED` needs nothing from you: the daemon has returned the issue to `implementing` (Dispatch `in_progress`) and started the **implementer**, whose correction goes through the tester and the reviewer again, never straight to retro. A `reviewer` notice with an `APPROVED` review means the daemon has started retro (step 5). An `implementer` notice for `production_check` is its production report: read the record on the pull request and the issue, then run step 7. A `tester` notice with `verdict: "fail"` — its handoff carries `implementerProof.verdict: "rejected"`, or a failure naming the production-like proof — has gone back to the **implementer** by the daemon's table; never supply the proof from another role. A worker that reports no surface reaches the changed path sends that report instead of completing its phase, so the daemon starts nothing more on that issue and the worker stays idle in its session, not suspended: file a child issue in this tree to build the surface (infrastructure, tooling, or a skill), and when that child's `child-closed` arrives, tell the waiting worker to continue with `envoy_publish` to its role topic. That report is never a reason to advance the phase. |
422
- | `pr-blocked` | Its `reason` names the pull request and the `max_fix_attempts` it reached, or reads `Issue reached review_round_cap=<N>.` (the end of this row). The count is of heads pushed onto a red verdict that changed something outside `.legion/` — handoff-only pushes (`.legion/` paths only) never count, a push by the review App (a planner's, tester's, reviewer's or architect's) never counts, and the head after a red the tester's red tests earned (a review-App push that changed a path outside `.legion/`, however many handoff-only pushes follow it) does not count either — so after the tester's handoff-only push onto the implementer's red, the implementer's next push does count; a push the daemon cannot classify (a listener without `changed_paths`, a list the listener stopped at 100 paths or 32,768 runes of text, a push listing no commits) does. Published once per exhausted count, not on every later red verdict for that count. Read the failed CI evidence and recovery attempts. The notice moves nothing, and no later CI red within the attempt that ran the count out (the counted head, and every head pushed on top of it until a push lands on a head CI judged green, the tester's red tests and handoff onto the held red included) sends the work back from `testing`, `reviewing`, `retro` or `merging` either: the issue stays in its phase until you move it, or a worker's own decision does (a tester's `fail`, a reviewer's request for changes). A head pushed onto green CI leaves that attempt, so its red still comes as a `checks-red`. In `implementing`, give the implementer the failing checks (`envoy_publish` to its role topic). In any later phase a worker holds, tell that worker (`envoy_publish` to its role topic) to move the issue back to `implementing` with `request_backward_move`, naming the failing checks, and the daemon starts the implementer; or file a corrective child. In `awaiting_merge`, where no worker holds a phase and a backward move is refused, open a `dispatch ask` naming the failing checks for the human who merges, as section 6 does for a conflict there. Do not treat the blocked PR as final. A `review_round_cap` reason is the implementer's round count instead: every move back to an earlier phase counts one, and the notice comes again with each round past the cap. It moves nothing either, since the round that reached the cap has already started its worker. Tell the rounds apart by what announced each: a tester's fail by its `phase-finished` with `verdict: "fail"`; a request for changes by the reviewer's `phase-finished` over a `CHANGES_REQUESTED` review; the daemon's own move by a `checks-red` notice, whose reason names a conflict (`the head conflicts with <base>`), the required checks that failed (`CI is red at <head>`), or the merge queue's failed merge and its failing run (`the merge queue took pull request #<n> out at READY's head …`); a worker's `request_backward_move` by a `phase-finished` from the role that asked, whose reason reaches only the task of the worker the move started, so ask that worker. Judge the cap by the rounds that are not conflicts. Conflict returns need nothing from you beyond the next round. Tester fails, requests for changes and CI-red returns (a `checks-red` notice is raised for CI only when a required check fails on code the branch pushed, or when the merge queue fails the merge) are the work going in circles: narrow it, re-plan it with the responsible worker, or ask a human with `dispatch ask`. Judge a worker's backward move by the reason that worker gives. A move you ordered for a conflict found before `awaiting_merge` (section 6) is a conflict return. The merger's move back to `reviewing` for a READY refusal (`READY_UNREVIEWED_CHANGE`, or `READY_NOT_APPROVED` when its task names no approved head), and the reviewer's no-fix request for changes that follows it so the tester runs the head, are not the work going in circles either. A move that sends back code found wrong counts with the tester fails. |
423
- | `pr-merged` | Its `reason` names the pull request. The PR merged, under the repository's rules, before the issue reached `awaiting_merge`. The workflow runs on and asks no one to merge it: the daemon starts the **implementer** on the production check once the issue gets there, and you start nothing. Its `phase-finished` for `production_check` is what brings you to step 7: verify the record on the pull request and this issue first, then sign off naming it with `sign_off`. A merge is not the close. |
447
+ | `phase-finished` | The daemon has already moved the issue to its next phase by its fixed table and started that phase's role; you start nothing. Read the committed handoff for the finishing phase; if it shows unresolved gaps, tell the role now working the issue (`envoy_publish` to its role topic). A `planner` notice that names a departure from the spec's design defers to section 1's full condition: when the approved Summary, Acceptance, scope and settled decisions still hold, the plan is the record; otherwise change the root spec and request approval again as section 1 says. A `reviewer` notice whose GitHub review is `CHANGES_REQUESTED` needs nothing from you: the daemon has returned the issue to `implementing` (Dispatch `in_progress`) and started the **implementer**, whose correction goes through the tester and the reviewer again, never straight to retro. A `reviewer` notice with an `APPROVED` review means the issue is in `accepting` and the acceptance is yours (section 6): read the evidence, then `sign_off` or send it back with `request_backward_move`. A `tester` notice with `verdict: "fail"` — its handoff carries `implementerProof.verdict: "rejected"`, or a failure naming the production-like proof — has gone back to the **implementer** by the daemon's table; never supply the proof from another role. A worker that reports no surface reaches the changed path sends that report instead of completing its phase, so the daemon starts nothing more on that issue and the worker stays idle in its session, not suspended: file a child issue in this tree to build the surface (infrastructure, tooling, or a skill), and when that child's `child-closed` arrives, tell the waiting worker to continue with `envoy_publish` to its role topic. That report is never a reason to advance the phase. |
448
+ | `pr-blocked` | Its `reason` names the pull request and the `max_fix_attempts` it reached, or reads `Issue reached review_round_cap=<N>.` (the end of this row). The count is of heads pushed onto a red verdict that changed something outside `.legion/` — handoff-only pushes (`.legion/` paths only) never count, a push by the review App (a planner's, tester's, reviewer's or architect's) never counts, and the head after a red the tester's red tests earned (a review-App push that changed a path outside `.legion/`, however many handoff-only pushes follow it) does not count either — so after the tester's handoff-only push onto the implementer's red, the implementer's next push does count; a push the daemon cannot classify (a listener without `changed_paths`, a list the listener stopped at 100 paths or 32,768 runes of text, a push listing no commits) does. Published once per exhausted count, not on every later red verdict for that count. Read the failed CI evidence and recovery attempts. The notice moves nothing, and no later CI red within the attempt that ran the count out (the counted head, and every head pushed on top of it until a push lands on a head CI judged green, the tester's red tests and handoff onto the held red included) sends the work back from `testing`, `reviewing`, `accepting`, `retro` or `merging` either: the issue stays in its phase until you move it, or a worker's own decision does (a tester's `fail`, a reviewer's request for changes). A head pushed onto green CI leaves that attempt, so its red still comes as a `checks-red`. In `implementing`, give the implementer the failing checks (`envoy_publish` to its role topic). In any later phase a worker holds, tell that worker (`envoy_publish` to its role topic) to move the issue back to `implementing` with `request_backward_move`, naming the failing checks, and the daemon starts the implementer; or file a corrective child. In `accepting`, where no worker holds a phase, the move is yours: `request_backward_move` with `issue`, naming the failing checks. In `awaiting_merge`, where no worker holds a phase and a backward move is refused, open a `dispatch ask` naming the failing checks for the human who merges, as section 6 does for a conflict there. Do not treat the blocked PR as final. A `review_round_cap` reason is the implementer's round count instead: every move back to an earlier phase counts one, and the notice comes again with each round past the cap. It moves nothing either, since the round that reached the cap has already started its worker. Tell the rounds apart by what announced each: a tester's fail by its `phase-finished` with `verdict: "fail"`; a request for changes by the reviewer's `phase-finished` over a `CHANGES_REQUESTED` review; the daemon's own move by a `checks-red` notice, whose reason names a conflict (`the head conflicts with <base>`), the required checks that failed (`CI is red at <head>`), or the merge queue's failed merge and its failing run (`the merge queue took pull request #<n> out at READY's head …`); a worker's `request_backward_move` by a `phase-finished` from the role that asked, whose reason reaches only the task of the worker the move started, so ask that worker; your own send-back from `accepting` by the reason you gave. Judge the cap by the rounds that are not conflicts. Conflict returns need nothing from you beyond the next round. Tester fails, requests for changes and CI-red returns (a `checks-red` notice is raised for CI only when a required check fails on code the branch pushed, or when the merge queue fails the merge) are the work going in circles: narrow it, re-plan it with the responsible worker, or ask a human with `dispatch ask`. Judge a worker's backward move by the reason that worker gives. A move you ordered for a conflict found before `awaiting_merge` (section 6) is a conflict return. The merger's move back to `reviewing` for a READY refusal (`READY_UNREVIEWED_CHANGE`, or `READY_NOT_APPROVED` when its task names no approved head), and the reviewer's no-fix request for changes that follows it so the tester runs the head, are not the work going in circles either. A move that sends back code found wrong counts with the tester fails. |
449
+ | `pr-merged` | Its `reason` names the pull request. The PR merged, under the repository's rules, before the issue reached `awaiting_merge`. The workflow runs on and asks no one to merge it: the merge closes the issue the moment it reaches `awaiting_merge` (section 7), and you start nothing; the production check after the close is the implementer's, on the pull request, and asks nothing of you. Until then the phases run as they would, your acceptance included. |
424
450
  | `pr-closed-unmerged` | Decide from current scope whether the work is reopened, started over (`park_child` then `rerun_child`, for a child), or ended with a reason. Delegate the repository action to the responsible phase worker and keep ownership. |
425
- | `merge-refused` | Its `reason` names the pull request, READY's head, what the daemon asked GitHub to do (merge, enqueue, or enable auto-merge for it), and GitHub's refusal, which a retry would meet again (squash merges disabled, a permission the implement App lacks). The daemon has stopped submitting that merge; the issue stays in `awaiting_merge`. The cause is a repository setting or an App permission, a person's to change: ask one with `dispatch ask`, naming the refusal and the pull request at READY's head, which that person merges under the repository's rules once it is fixed. The merge moves the issue on to its production check. Never bypass a rule. |
426
- | `merge-stalled` | Its `reason` names the pull request, the state and head GitHub shows (closed, or another head), since when GitHub has shown it, and READY's head, which the record still awaits. GitHub's last change to the pull request is more than 10 minutes old and the record never heard of it, so its webhook never reached the daemon: the daemon has stopped submitting that merge, and the issue stays in `awaiting_merge`. Read the pull request on GitHub. Open at READY's head, GitHub has caught up: a person merges it under the repository's rules, and the merge moves the issue on to its production check. Closed, or at another head the daemon never recorded: ask a person with `dispatch ask`, naming the pull request, what GitHub shows, and READY's head. Never bypass a rule. |
427
- | `merge-removed` | Its `reason` names who took the pull request out of the merge queue or turned its auto-merge off at READY's head after the daemon submitted it, or says GitHub turned it off on its own (over a repository setting such as a merge method the repository blocks) and names the App that submitted the merge, which GitHub names as the actor of its own disables; then what was removed, GitHub's reason (`manual`, `merge_conflict`, `manually_disabled`, `merge_commit_blocked`, …), when, and READY's head. It was not a failed merge, which comes as a `checks-red` instead. The daemon submits that merge no further, so the removal stands, and the issue stays in `awaiting_merge`. Read the pull request on GitHub. A `merge_conflict` conflicts with the base or with a pull request queued ahead of it: once the conflict is on the base, the daemon's own conflict check sends the issue back to `implementing` by itself. Otherwise ask a person with `dispatch ask` (the one who removed it, when the reason names a person rather than GitHub on its own), naming the pull request at READY's head and the reason; that person merges or queues it again under the repository's rules, and the merge moves the issue on to its production check. Never bypass a rule. |
451
+ | `merge-refused` | Its `reason` names the pull request, READY's head, what the daemon asked GitHub to do (merge, enqueue, or enable auto-merge for it), and GitHub's refusal, which a retry would meet again (squash merges disabled, a permission the implement App lacks). The daemon has stopped submitting that merge; the issue stays in `awaiting_merge`. The cause is a repository setting or an App permission, a person's to change: ask one with `dispatch ask`, naming the refusal and the pull request at READY's head, which that person merges under the repository's rules once it is fixed. The merge closes the issue. Never bypass a rule. |
452
+ | `merge-stalled` | Its `reason` names the pull request, the state and head GitHub shows (closed, or another head), since when GitHub has shown it, and READY's head, which the record still awaits. GitHub's last change to the pull request is more than 10 minutes old and the record never heard of it, so its webhook never reached the daemon: the daemon has stopped submitting that merge, and the issue stays in `awaiting_merge`. Read the pull request on GitHub. Open at READY's head, GitHub has caught up: a person merges it under the repository's rules, and the merge closes the issue. Closed, or at another head the daemon never recorded: ask a person with `dispatch ask`, naming the pull request, what GitHub shows, and READY's head. Never bypass a rule. |
453
+ | `merge-removed` | Its `reason` names who took the pull request out of the merge queue or turned its auto-merge off at READY's head after the daemon submitted it, or says GitHub turned it off on its own (over a repository setting such as a merge method the repository blocks) and names the App that submitted the merge, which GitHub names as the actor of its own disables; then what was removed, GitHub's reason (`manual`, `merge_conflict`, `manually_disabled`, `merge_commit_blocked`, …), when, and READY's head. It was not a failed merge, which comes as a `checks-red` instead. The daemon submits that merge no further, so the removal stands, and the issue stays in `awaiting_merge`. Read the pull request on GitHub. A `merge_conflict` conflicts with the base or with a pull request queued ahead of it: once the conflict is on the base, the daemon's own conflict check sends the issue back to `implementing` by itself. Otherwise ask a person with `dispatch ask` (the one who removed it, when the reason names a person rather than GitHub on its own), naming the pull request at READY's head and the reason; that person merges or queues it again under the repository's rules, and the merge closes the issue. Never bypass a rule. |
428
454
  | A reply on an ask you follow | Interpret the reply in the issue's design context. Answer in its thread (`dispatch comment --reply-to <comment id>`; under an open ask whose next move is yours, such as the approval request you must revise or hand back, `--reply-to-ask <ask id> --turn agent`, since a default-turn reply hands that request back to the human and a corrected `--summary` is then refused), then adjust the plan or relay it via `envoy_publish` to the responsible worker's role token; scope and product decisions remain with you. |
429
455
  | `worker-died` | Its `role` and `phase`. That role's claim failed: its launches or prompts ran out. For a phase worker the daemon holds the issue (phase `held`) and starts nothing more on it. Reassess the work, then decide with `retry_or_escalate`: `retry` when the failure looks agent-specific or transient, `escalate` to hand the held issue to the controller when it looks environmental. |
430
456
  | `held` | Its `role` and `phase` (the phase the issue left), or `phase` with `reason: "escalated"`. Without `reason`, that phase's worker ran out of launches or prompts: the issue is held (phase `held`), the `worker-died` that comes with it is yours to answer with `retry_or_escalate` as that row says, and the controller hears of the hold too. With `reason: "escalated"`, it records your own `escalate`: the controller has the issue now, and you start nothing for it. |
@@ -269,9 +269,9 @@ leans on `External links:`, and the label row is the one that never depends on h
269
269
 
270
270
  - `OPEN`: work in flight. Skip it; the issue stays where it is.
271
271
  - `MERGED`: the change landed. Take nothing and set nothing: an issue Legion ran is already skipped
272
- by the `Legion ran it without the label now on it` row, and the daemon moves such an issue to its
273
- production check itself on the merge event; one Legion did not run is someone's finished work with
274
- the issue left open. Skip it and name it in your summary
272
+ by the `Legion ran it without the label now on it` row, and the daemon closes such an issue
273
+ itself on the merge event (its implementer's production check follows the close); one Legion did
274
+ not run is someone's finished work with the issue left open. Skip it and name it in your summary
275
275
  (`<KEY>: pull request <url> merged, the issue is still todo`) so a person closes it.
276
276
  - `CLOSED` (not merged): someone abandoned the change. Skip it and name it in your summary; the
277
277
  issue's owner decides what follows. For an issue Legion runs, the daemon tells its architect
@@ -20,7 +20,9 @@ retrospective's durable output.
20
20
 
21
21
  1. Tester green and all code-review cycles finish.
22
22
  2. The reviewer approves the head. It still carries the issue's handoffs, `.legion/<issue>/`
23
- (`<issue>` is your `LEGION_ISSUE`), which every tester and reviewer round writes again.
23
+ (`<issue>` is your `LEGION_ISSUE`), which every tester and reviewer round writes again. The
24
+ architect then accepts the issue (`accepting`) with `sign_off`, which starts this retro; one it
25
+ sends back to `implementing` or `testing` instead runs those phases again first.
24
26
  3. Run this retro (*Durable outputs*, below): its learnings under `docs/solutions/`, then one final
25
27
  commit removing `.legion/<issue>/`, pushed together, and the retro message on the Dispatch
26
28
  issue. Retro writes **no handoff**. The removal exists because a squash merge commits the head
@@ -32,13 +34,14 @@ retrospective's durable output.
32
34
  posts it on the Dispatch issue and publishes it to the project's merge-queue role when one is
33
35
  configured. On READY's acceptance the daemon submits the merge, and it lands under the
34
36
  repository's rules: its required reviews and checks, and its merge queue when it enables one.
35
- 5. After that merge, the implementer — not the reviewer or merger — verifies the change in production
36
- and records it on the PR and the issue: the agent that developed it is responsible for testing
37
- in production. The architect's sign-off waits for that record.
38
- The record is the pull request's `Production:` line, one pull-request comment, and a
39
- `dispatch message` on the issue, each naming what was driven, how, what was observed, and the
40
- merge commit. A defect the production check finds becomes a corrective child issue of the same tree,
41
- owned by the architect and implemented by the same implementer; the parent stays open until it lands.
37
+ 5. That merge closes the issue: the daemon writes `done`, and the implementer — not the reviewer or
38
+ merger — is handed the production check in its live session, as work after the close: the agent
39
+ that developed the change is responsible for testing it in production, once production carries
40
+ the merge. The record is the pull request's `Production:` line and one pull-request comment,
41
+ naming what was driven, how, what was observed, the merge commit and what woke the look; nothing
42
+ is written on the closed issue, since Dispatch refuses it. A defect the check finds is filed as
43
+ an issue of its own in the project, never as a child of the closed one
44
+ (`skill://legion-worker/references/merge-gate.md`, *The production check after the close*).
42
45
 
43
46
  Retro's commits sit above the reviewer's approved head and the approval stands: commits that change
44
47
  only `docs/solutions/`, and the one that removes `.legion/<issue>/`, do not void it, and the tree
@@ -47,7 +50,7 @@ the approved head with no review round after it brings the base's paths above th
47
50
  refuses it (`READY_UNREVIEWED_CHANGE`) and the reviewer reviews the new head as a new round; one the
48
51
  conflict procedure sends back through `implementing` is confirmed before READY. Any round after
49
52
  retro (a conflict round, a round a red CI sends back, a re-review) writes `.legion/<issue>/` again,
50
- and every approval moves the issue to retro once more: each retro ends with the removal again, or
53
+ and every approval, through the architect's acceptance, moves the issue to retro once more: each retro ends with the removal again, or
51
54
  READY is refused.
52
55
 
53
56
  Do not start retro before step 2 or skip it because the change seems mechanical; the merger's
@@ -174,7 +177,7 @@ Dispatch message on
174
177
  the issue — `--issue` is your `LEGION_ISSUE`; Legion issues live on Dispatch, never on a GitHub
175
178
  issue, so no `gh issue` write and no GitHub-issue comment — naming the documents, the
176
179
  one-to-three most useful takeaways, the two proofs you read, and the production check that
177
- follows the merge. The message must carry this revived implementer's structured
180
+ follows the merge's close of the issue. The message must carry this revived implementer's structured
178
181
  attribution footer with `phase` set to `retro`; the body is capped at 2,000 characters:
179
182
 
180
183
  ```bash
@@ -189,7 +192,7 @@ dispatch message --issue <KEY> --body-file - <<'EOF'
189
192
 
190
193
  **Proofs read:** implementer <surface/command>, tester <surface/command>.
191
194
 
192
- **Production check:** <what the implementer will drive after the merge, and any deploy or restart it waits on first, with the agent or role the deployment instructions name to perform it, or the person it asks when they name none>
195
+ **Production check:** <what the implementer will drive in production once the merge closes the issue and production carries it, and the deploy or restart that carries it there, with the agent or role the deployment instructions name to perform it, or the person it asks when they name none; no reply is awaited, the daemon wakes the check on the deploy's event>
193
196
 
194
197
  <!-- legion: {"session":"<session-id>","phase":"retro"} -->
195
198
  EOF