@sjawhar/pi-legion 11.0.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +5 -4
  2. package/agents/plan-gap-analyst.md +24 -16
  3. package/agents/plan-reviewer.md +59 -16
  4. package/dist/legion.js +179 -61
  5. package/dist/skills/leading-a-work-stream/SKILL.md +96 -0
  6. package/dist/skills/leading-a-work-stream/references/daily-plan.md +8 -0
  7. package/dist/skills/leading-a-work-stream/references/decision-rights.md +6 -0
  8. package/dist/skills/leading-a-work-stream/references/direction-and-coaching.md +13 -0
  9. package/dist/skills/leading-a-work-stream/references/dispatch-upkeep.md +7 -0
  10. package/dist/skills/leading-a-work-stream/references/sources.md +9 -0
  11. package/dist/skills/leading-a-work-stream/references/speed-tick.md +44 -0
  12. package/dist/skills/leading-a-work-stream/references/user-quotes.md +7 -0
  13. package/dist/skills/legion-architect/SKILL.md +11 -8
  14. package/dist/skills/legion-architect/references/acceptance.md +18 -5
  15. package/dist/skills/legion-architect/references/decomposition.md +3 -2
  16. package/dist/skills/legion-architect/references/design-gate.md +42 -19
  17. package/dist/skills/legion-architect/references/wake-routing.md +4 -4
  18. package/dist/skills/legion-controller/SKILL.md +31 -17
  19. package/dist/skills/legion-controller/references/admission.md +5 -3
  20. package/dist/skills/legion-controller/references/backlog-stewardship.md +17 -2
  21. package/dist/skills/legion-controller/references/daily-report.md +4 -4
  22. package/dist/skills/legion-controller/references/finding-asks.md +111 -14
  23. package/dist/skills/legion-controller/references/slack-mentions.md +2 -2
  24. package/dist/skills/legion-controller/references/triage.md +9 -5
  25. package/dist/skills/legion-controller/references/wakes.md +22 -8
  26. package/dist/skills/legion-worker/SKILL.md +7 -6
  27. package/dist/skills/legion-worker/references/conflicts-and-rewrites.md +23 -16
  28. package/dist/skills/legion-worker/references/findings.md +126 -31
  29. package/dist/skills/legion-worker/references/merge-gate.md +57 -25
  30. package/dist/skills/legion-worker/references/pr-body.md +9 -5
  31. package/dist/skills/legion-worker/references/skip-checks-trailer.md +1 -1
  32. package/package.json +2 -2
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: leading-a-work-stream
3
+ description: Use when you lead a work stream or team of agents, when an agent asks you to approve, confirm or review its step or pull request, when you want to know the state of the stream, when an agent starts a long project, or when you consider building tooling or a restriction for agents.
4
+ ---
5
+
6
+ # Leading a work stream
7
+
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.
9
+
10
+ A lead raises the stream's numbers by making its agents faster, and is not a gate: agents waiting on your reply are a queue, and a queue is the stream's largest hidden cost. Keep it empty — answer at once, or reply "your call" — and when one kind of question keeps arriving, write the answer into the stream's plan or skill, or build the tool that makes the question unnecessary. The stream's own facts (its numbers, scoreboard format, plan, dashboard) are in its issue spec or the organization's stream document; read them there.
11
+
12
+ In a Legion tree, the daemon's workflow and your role prompt decide who starts a worker, who accepts the work and how it merges. This skill does not change that sequence. There, a tool the stream needs is a child of your tree or a finding (`skill://legion-worker/references/findings.md`), not an agent you start on your own. Why each rule below works: [sources.md](skill://leading-a-work-stream/references/sources.md).
13
+
14
+ ## What a lead does
15
+
16
+ 1. **Sets direction**: the numbers and targets, the bottleneck, and which experiments run in what order, written where every agent can read it, so each agent constrains its own choices by it. How to open the stream's issue and get its three lines from the user: [direction-and-coaching.md](skill://leading-a-work-stream/references/direction-and-coaching.md).
17
+ 2. **Removes obstacles** its agents cannot: access, a decision above their authority, a conflict with another stream.
18
+ 3. **Checks results against the numbers**, not against its own reading of the work.
19
+ 4. **Coaches each agent's loop**: does it measure its number, write a prediction before each change, and compare more than one design? Give procedure, not solutions, because the agent has the facts of its own work. Which workflow a change or an experiment runs through, and what it predicts before it starts: [direction-and-coaching.md](skill://leading-a-work-stream/references/direction-and-coaching.md).
20
+ 5. **Makes the stream faster**: finds where agents lose time and changes the skill, tool or step that causes it.
21
+ 6. **Proves its facts with a command.** A claim about what exists or what a thing can do rests on a command and its output, not on a reading. A claim that nothing exists rests on a command whose search could have found it: state the search and why it could match. A lead's facts about its own stream are the ones nobody else checks.
22
+ 7. **Keeps the stream's record of what each agent accepted.** At each check-in, read it against the agents' issues and open asks. An item that is neither done, in progress, nor an open ask is dropped work. The lead finds its owner and has it recorded at once.
23
+
24
+ ## The speed loop
25
+
26
+ Arm a reminder that wakes you every 3 hours and run the six-step loop it names: [speed-tick.md](skill://leading-a-work-stream/references/speed-tick.md). A reminder inside the session dies with the session, and a stream nobody measures for speed slows to the pace of its slowest wait.
27
+
28
+ ## Dates
29
+
30
+ A date is the time the work takes at agent speed, plus only the waits nobody can shorten. Agents run in parallel and around the clock, so a day of agent work is due tomorrow, and ten minutes of work is due within the hour.
31
+
32
+ - Each date carries its basis in one line ("about 3 h of work, 2 h of benchmark runs"), so padding is visible.
33
+ - A key performance indicator (KPI) is one of the stream's numbers in its issue spec. A KPI target's date is the earliest date the fastest plan you can write down reaches it. Then shorten the plan: more agents in parallel, the slow step removed, a first slice that lands today.
34
+ - When a date will slip, say so the moment you know, with the new date and why. A date beaten by days was padded: set the next date for that kind of work earlier by the margin you beat this one by.
35
+
36
+ ## What a lead does not do
37
+
38
+ - Gate a decision an agent can make. A concern about a reversible step goes to the agent as a constraint, and the agent decides.
39
+ - Review every pull request. Peer review and tests are the approval.
40
+ - Require a plan, spec or confirmation to be sent to it before an agent acts.
41
+ - Ask agents for a report of each decision or step. Read results in GitHub, Dispatch and the numbers, and measure a number with a command you run.
42
+ - Ration a shared resource (disk, VMs, compute) by approving each use. Set the limit, and the agents apply it themselves or through a tool.
43
+ - Relay messages between agents who can talk directly.
44
+ - Give an agent orders specific to its own work (which task to launch, at what size, what to regrade): the agent has the facts of its own work and the lead does not. Give the rule and the goal (the target, the budget, the bottleneck) and let each agent choose its steps. Before you pass on a precondition from another agent, check it against the code or have its owner send it directly.
45
+
46
+ ## Decision rights
47
+
48
+ A step that is easy to undo is the agent's: it acts and reports to nobody, and you read the result in GitHub, Dispatch and the numbers. A step that is hard to undo goes from the agent to its owner directly — a person through that agent's own Dispatch ask, the other stream's lead, the owner of the shared infrastructure — never through you, because a relay adds a wait and loses the agent's own facts. Which steps fall where: [decision-rights.md](skill://leading-a-work-stream/references/decision-rights.md).
49
+
50
+ When an agent asks permission for an easy-to-undo step, reply "your call" and state any constraint it must keep; add no check of your own before it may act. Do not send a "yes" to an agent that said it would not wait, because the reply arrives as an interruption with nothing in it.
51
+
52
+ ## Rules reach agents through what they read
53
+
54
+ A rule sent only by message reaches the agents online that day, in the lead's paraphrase, and is gone for the next session. Put each rule where agents read it before they act — the skill that covers the step, the stream's brief, the repository's own instructions — written as an instruction at the step it governs.
55
+
56
+ Keep one record of the words of the person the stream works for, each quoted with its date and source, and link that quote wherever a text says the person wants something ([user-quotes.md](skill://leading-a-work-stream/references/user-quotes.md)). Never shorten a quote into a stronger rule ("don't regrade his finished versions without asking him" is not "never regrade"), and never turn a direction into a number the person did not give.
57
+
58
+ ## Keep every request and wait in Dispatch
59
+
60
+ You answer for every request the user gives any of your agents, and for every wait any of them has.
61
+
62
+ - **A request from the user goes on a claimed Dispatch issue before work on it starts**: a line in that issue's `open-items.md` artifact, never its spec, since each spec edit after approval is a new version that closes the design gate. Add it within the hour — what, who asked, a link to the source, what done means (deployed, merged, measured) and a date. A line leaves only with a link to the evidence that it is done, or to the user's agreement that it is dropped.
63
+ - **Done is delivered and checked: you saw the result yourself** (deployed, merged, measured). Written into a spec, an approval requested, a todo closed or a message sent to an agent is not done.
64
+ - **A wait on a person is an open Dispatch ask the moment you know it** — never only a chat question, a note, a peer message, a comment on an answered ask, or a review request, because nobody tracks those. A wait on anything else is an `open-items.md` line naming the blocker, its owner and its link. Keep working on everything else.
65
+ - **Every hour, run the stream's Dispatch check,** the command its brief names. **Once a day, run the repository's dropped-work audit over each agent's transcript and your own;** it also lists long idle spans with work open and long projects that do not use their workflow skill. Each agent gets its own findings directly, and you write in the stream's issue how many items each audit found.
66
+ - Three more rules of this upkeep — checking a delegated result, a step held back from a hand-over, and what to re-read after a restart — are in [dispatch-upkeep.md](skill://leading-a-work-stream/references/dispatch-upkeep.md).
67
+
68
+ ## Plan the day with the team
69
+
70
+ Every morning by 09:00 Pacific, you and your agents agree on Envoy what the stream will merge today, and you write that list into the stream's record, checking that each item has an agent that committed to land it; without it each agent optimises its own day and the stream's numbers move by accident. How the planning runs, what an item must say, and the end-of-day comparison: [daily-plan.md](skill://leading-a-work-stream/references/daily-plan.md).
71
+
72
+ ## Knowing the state of the stream
73
+
74
+ From records you read yourself (GitHub, Dispatch, the numbers), answer: what is the target; what is the actual value now; what is the obstacle, and which one is being worked on; what is the next step and what should it do to the number; when will we know? Message an agent to plan the day with it, to remove an obstacle or to change its direction, not to collect status.
75
+
76
+ ## Before you say something is blocked
77
+
78
+ **Read the thing itself, not the thing next to it.** Before you write that X is blocked by Y, read X's own state: `gh pr checks` at the head, not the queue's length; the process (`ps -eo pid,etimes,args | grep <session-id>`) and the session's last tool call, not a registry's session list; the job's own start time, not the pool's history. In one day on one box this error was made four times and two of those reached every stream; each was cheap to check and expensive to act on, because a stopped resource and a contended one look identical from a queued job, and a session waiting for its workers looks identical to a dead one.
79
+
80
+ **A blocker you relay to other streams carries the command that shows it.** Without it, each stream spends a check to disprove it after acting on it.
81
+
82
+ **Ask a fresh reviewer, for each claimed cause, to name the command or record that would show it FALSE, and to run it.** A reviewer that reads only the prose confirms a confident wrong cause. The causes that cost most are the ones nobody could falsify, because nobody looked for what would disprove them.
83
+
84
+ **Run a watch that names quiet sessions, and let it restart nothing.** A session that dies mid-task stays dead until a person notices: measured at about 7 hours on a day when one credential failure stopped a box, and at 5 minutes or less once a watch existed. A watch reads the session's transcript modification time, its process and, if it can, its pane; it reports, and the owner decides. Two traps: a systemd user service on a dev box may not reach the tmux server at all (it answers `server exited unexpectedly` while the same command works from a pane), and a watch built on an agent-messaging registry reports live sessions as dead under load. Test it by making it report something you know is true.
85
+
86
+ ## Delegation and tooling
87
+
88
+ - Use subagents and peer agents for review, research and skill improvement. Delegation keeps the responsibility with you: when a delegated result lands, read the number it was meant to move yourself.
89
+ - When an agent starts a long project, check that it uses the workflow skill for that kind of work and name the skill: the `/sdd` workflow for an engineering project, `building-and-delivering-tasks` for RL task work. That skill's own review steps replace review by the lead.
90
+ - When agents keep losing time to the same chore, start an agent to build the tool that removes it. Do not wait to be asked.
91
+ - Do not build, file or ask for a restriction, guard or gate against a failure nobody has seen. Fix a real failure at its cause, after it happens.
92
+ - When the user asks the stream for an explainer video, you own it: have a subagent make it with the `making-explainer-videos` skill.
93
+
94
+ ## Improving this skill
95
+
96
+ When a rule here failed or was missing, edit this file directly, and put the evidence in the commit message, so the next lead gets the fix instead of the same failure.
@@ -0,0 +1,8 @@
1
+ # Planning the day with the team
2
+
3
+ Every morning, by 09:00 Pacific, the lead and its agents agree on Envoy what the stream will merge today, as a working team does at its daily planning: each agent says what it can land and what stands in the way, the team settles the list, and the lead writes it into the stream's record. The lead owns the list and that it is real.
4
+
5
+ - Each item starts with the key performance indicator (KPI, one of the stream's numbers) it moves and the change expected, for example "Grade wall time 7,104 s -> 5,700 s: ...", so the day can be checked against the numbers.
6
+ - Work that moves no KPI goes on the list only when it unblocks an item that does, and names that item.
7
+ - During the day, an agent that will miss an item says so as soon as it knows, so the team can move work.
8
+ - At the end of the day, post each item's actual KPI reading next to its prediction in the stream's record, and ask the owner of each missed item on Envoy what blocked it.
@@ -0,0 +1,6 @@
1
+ # Decision rights
2
+
3
+ | The step | Who decides |
4
+ | --- | --- |
5
+ | Easy to undo: a code change, a flag, a branch, opening or merging a pull request that passed peer review and tests, a planned experiment, and any spending the workflow itself calls for (a paid-API review, compute, a VM, a model run the task needs) | The agent. It acts and reports to nobody: the lead reads the result in GitHub, Dispatch and the numbers. |
6
+ | Hard to undo: deleting data someone else created, a new financial commitment (a contract, a subscription), a message outside the organization, security, another stream's work or shared state | The agent takes it to its owner directly: a person through the agent's own Dispatch ask, the other stream's agent or lead, the owner of the shared infrastructure. It does not pass through the lead. |
@@ -0,0 +1,13 @@
1
+ # Setting direction and coaching the loop
2
+
3
+ ## The stream's three lines
4
+
5
+ Open the stream's issue with three lines above its targets: the problem the stream exists to solve, the one approach it commits to, and what it will not do. Agents use the third line as a constraint on their own choices, so without it they take work the stream decided against.
6
+
7
+ Ask the user those three questions once, in one message, each with a draft answer taken from the user's own words. If an answer rules no work in and none out, ask once more with two concrete options.
8
+
9
+ ## Coaching an agent's loop
10
+
11
+ - An experiment on a number, with a benchmark that runs in minutes, goes through `/autoresearch`: the expected gain is in its notes before each run, and the change is run again before it is kept, so a result that came from noise does not survive.
12
+ - Use the `ce-optimize` skill instead when the result is noisy or has several objectives.
13
+ - A one-off change still gets its prediction written in the scoreboard before it starts, so a wrong prediction is visible instead of explained away afterwards.
@@ -0,0 +1,7 @@
1
+ # Dispatch upkeep: the rest of the lead's rules
2
+
3
+ These go with the "Keep every request and wait in Dispatch" section of the skill.
4
+
5
+ - **Check a delegated or relayed result against its done before you report it**, because an agent's "done" is often a message sent, not a thing delivered. Each follow-up the result names becomes a claimed issue, an ask, or an `open-items.md` line, the same hour.
6
+ - **A step you keep back from a hand-over becomes its own claimed issue,** blocked by the handed-over one, or it is lost when the hand-over closes.
7
+ - **After a restart or a compaction, first re-read your claimed issues and your open asks** (`dispatch open-asks`), then the transcript since your last audit, because what you were waiting for is not in the new context.
@@ -0,0 +1,9 @@
1
+ # Why these rules
2
+
3
+ - Bezos, [2015 shareholder letter](https://www.sec.gov/Archives/edgar/data/1018724/000119312516530910/d168744dex991.htm): reversible decisions go to individuals, fast; a heavy process on them causes "slowness, unthoughtful risk aversion".
4
+ - DORA, [Streamlining change approval](https://dora.dev/capabilities/streamlining-change-approval/): external approval slows delivery and does not cut failed changes; peer review plus automation works; more process after problems makes things worse.
5
+ - US Army, [ADP 6-0 Mission Command](https://armypubs.army.mil/epubs/DR_pubs/DR_a/ARN47032-ADP_6-0-000-WEB-1.pdf), 1-37 to 1-44: act within intent; delegation cuts response time; responsibility stays with the commander.
6
+ - Google re:Work, [research behind great managers](https://rework.withgoogle.com/intl/en/guides/following-the-data-the-research-behind-great-managers): good managers coach and "empower the team without micromanaging".
7
+ - Rother & Liker, [A Kata for PDCA](https://cdn.prod.website-files.com/68b9f0686639ca6b3c064d61/68dd8a5720bf6d3042bafc50_a_kata_for_pdca_-_target_summer_2014.pdf), and [LEI, Kata](https://www.lean.org/lexicon-terms/kata/): the five questions; the coach gives procedure, not solutions.
8
+ - Reinertsen, [Product Development Flow, ch. 1](http://lpd2.com/wp-content/uploads/2013/06/ReinertsenFLOWChap1.pdf): queues are the largest hidden cost.
9
+ - [Summary of Grove's High Output Management](https://www.becausetech.rocks/blog/high-output-management/): meddling makes people refer problems up; follow delegated work through.
@@ -0,0 +1,44 @@
1
+ # The speed tick: the 3-hourly loop and a reminder that survives restarts
2
+
3
+ ## The loop, on each tick
4
+
5
+ 1. Read the stream's state from its records: the numbers, today's plan against what merged, the hourly Dispatch check.
6
+ 2. Ask each agent on Envoy what slows it down most right now. Not status.
7
+ 3. Answer in writing: how can I help this go faster while the targets and the checks that gate them stay unchanged; how can I do better work faster; how can I help the team do better work faster?
8
+ 4. Give the answers to a fresh subagent to attack — is each target ambitious, is each change concrete, is each date padded — and rewrite what it finds weak, because your own answers read better to you than they are.
9
+ 5. Make the change now, or start an agent on it.
10
+ 6. Append the tick to the stream's speed log (an artifact `speed-log.md` on the stream issue): the time, the change, the number it should move and by how much; on the next tick, what it did.
11
+
12
+ ## Arming the reminder
13
+
14
+ A reminder inside the session (`sleep` in a background job) dies with the session's processes. A systemd user timer survives them and wakes the session with an Envoy message. Arm it once, from a shell on the machine the session runs on.
15
+
16
+ Replace `NAME` with a short name for your stream and `SESSION` with your full session id. The timer below fires at 01, 04, 07, 10, 13, 16, 19 and 22 UTC; change `OnCalendar` for another rhythm.
17
+
18
+ ```bash
19
+ mkdir -p ~/.config/systemd/user
20
+ cat > ~/.config/systemd/user/speed-tick-NAME.service <<'EOF'
21
+ [Unit]
22
+ Description=Speed tick for NAME's lead
23
+
24
+ [Service]
25
+ Type=oneshot
26
+ ExecStart=<envoy-send-command> SESSION "SPEED TICK: run the six-step loop in leading-a-work-stream references/speed-tick.md now."
27
+ EOF
28
+ cat > ~/.config/systemd/user/speed-tick-NAME.timer <<'EOF'
29
+ [Unit]
30
+ Description=Speed tick for NAME's lead, every 3 hours
31
+
32
+ [Timer]
33
+ OnCalendar=*-*-* 01/3:00:00
34
+ Persistent=true
35
+
36
+ [Install]
37
+ WantedBy=timers.target
38
+ EOF
39
+ systemctl --user daemon-reload
40
+ systemctl --user enable --now speed-tick-NAME.timer
41
+ systemctl --user list-timers speed-tick-NAME.timer
42
+ ```
43
+
44
+ Set `ExecStart` to the Envoy send command the deployment provides. A session that runs where it cannot install a user timer (a pod) arms an equivalent wake-up there, and says in its speed log how.
@@ -0,0 +1,7 @@
1
+ # The record of the user's own words
2
+
3
+ Keep one record of the words of the person the stream works for, each quoted with its date and source.
4
+
5
+ - A skill, brief, spec or message that says that person wants something links the quote. Without a quote, it names whose rule it is, so nobody takes an agent's invention for the user's instruction.
6
+ - When a later quote changes an earlier one, the record says which one stands, and every text that used the earlier one is changed the same day; otherwise two texts give agents opposite rules.
7
+ - Never shorten a quote into a stronger rule ("don't regrade his finished versions without asking him" is not "never regrade"), and never turn a direction into a number the person did not give.
@@ -13,9 +13,10 @@ You own one issue tree from its first decision to the merge that closes it. The
13
13
 
14
14
  - Act on delivered wakes and the live artifacts they name; build no wait loop, since every wake reaches you.
15
15
  - Check each claim against the code as fetched now (the default branch your addressing line names, or the head under review), never the workspace as it was at admission, and tell every fresh reader you dispatch to do the same: the branch may have moved since.
16
- - Before you end a turn that waits on a human, open what they must answer: a decision block, a `dispatch ask` or `dispatch request-approval`. A turn that ends with nothing open asks nobody, and the tree stops.
16
+ - Before you end a turn that waits on a human, open what they must answer: a decision block, a `dispatch ask` or `dispatch request-approval`. A turn that ends with nothing open asks nobody, and the tree stops. Open an ordinary ask on the root issue itself, never a child: only a question a session of this tree opens on the root starts a wait on a person, so an ask on a child leaves the root holding its slot while nothing runs. Once you have handed a root question to the human, end your turn: when nothing else holds the slot — no other issue of the tree in a phase, the `legion` label still on, and no person or outside session holding the root's Dispatch claim — the root returns its admission slot (`awaiting_person`), the daemon suspends this session at the end of the turn, and the human's answer resumes it with a task naming what answered and what is still with them. The same holds once you request approval and `register_gate` that version: the registration hands the spec to the human, so end your turn there too, and the human's review, or a newer version once Dispatch shows the request back on your turn, resumes you.
17
17
  - Deliver every criterion of the root spec in this tree. The only way to move work out is a child issue you create and own, or, when a root splits, a `dispatch ask` for the rest: work outside has no owner.
18
- - A problem outside the tree is a `dispatch ask`, never an issue you file, because a person decides whether it needs one (`skill://legion-worker/references/findings.md`).
18
+ - A problem outside the tree is a `dispatch ask`, never an issue you file, because a person decides whether it needs one (`skill://legion-worker/references/findings.md`). A clear defect is the exception. Fix one in code this tree touches or depends on in this tree's pull request. Send any other to the controller, which gives it to the tree that owns that code.
19
+ - Before you write a spec or ask a person anything, read the repository's `STRATEGY.md` when it has one, then use a standard best-practice solution; ask only what neither settles, with one recommendation. A design that crosses a Boundary in that file goes to its owner before it is built. Find the standard with a web search and with how two or three well-regarded projects solve the problem. Cite them in a few lines of the spec's `Design`. A design far from the standard is a sign to fix the underlying problem, not to add a workaround.
19
20
  - Write lifecycle changes with the `legion` tool, which takes Dispatch issue keys (`LEGION-41`). Never apply a label: Legion has none.
20
21
  - Message a phase worker with `envoy_publish` to `notifications.role.<token>`, with a token you hold (yours or your addressing line's) or one `roleToken` from `@legion/contracts` computes: a hand-made token may reach nobody.
21
22
  - Deployment instructions override this skill where they conflict: they are the operator's rules (required checks, deploy commands, code owners, standing roles you may consult, the merge credential).
@@ -28,22 +29,23 @@ You own one issue tree from its first decision to the merge that closes it. The
28
29
  - Every child names the running system its criteria are proven on (the command, service or page the tester drives) and the repository skill that drives it. If the repository cannot exercise a criterion end to end, building that path is a child of this tree.
29
30
  - The issue's primary document is the root spec: extend it in place, because a second "spec" artifact replaces the human's document. The waves, the proof of each outcome and the integration test go in the children and `.legion/<issue>/plan.json`, not the root spec.
30
31
  - Read `skill://legion-architect/references/design-gate.md` before you write the root spec and before any edit to it after approval, because any new version closes the gate. It also says which gate runs, and that a sub-architect runs none.
31
- - A root architect then ends its turn and releases no wave until a delivered wake shows `design-approved`: the daemon starts no phase in the tree before it. A sub-architect waits for none and releases its children with `release_children`.
32
+ - A root architect then ends its turn and releases no wave until a delivered wake shows `design-approved`: the daemon starts no phase in the tree before it. A root that waited on a person's answer gets no `design-approved` notice: a resume task saying "this resume is your design-approved wake" is that wake. A sub-architect waits for none and releases its children with `release_children`.
32
33
 
33
34
  ## 2. Children in flight
34
35
 
35
36
  - Set a child's dependencies in one call naming every issue it waits on: `dispatch issue-update --issue <child> --blocked-by <a> --blocked-by <b>`, or `--blocked-by` on `dispatch issue` at creation. The call replaces the child's whole list, so read its existing links first (`dispatch read`). Release it with the rest: `legion({ op: "release_children", issues: ["LEGION-41", "LEGION-42"] })`. Legion holds a released child that waits on an issue not `done` and starts it itself at its last blocker's close. A child that builds on another repository's merged change is not held this way: release it as `skill://legion-architect/references/decomposition.md` "Across repositories" says.
36
- - On each `child-closed`, read the child's handoff. Edit the spec of each open child the result changes, take out each child it makes unneeded with `park_child` and say why with `dispatch comment`, and release each child that can now start.
37
+ - Release every child as soon as it is filed, a later wave's included, each with `--blocked-by` the children it builds on, and never hold a release back for a close: a released child, held or running, keeps the root's close waiting, but once the root's own pull request has merged the root closes the moment its last released child leaves, and a child released after that finds no live tree and runs as an orphan root of its own.
38
+ - On each `child-closed`, read the child's handoff. Edit the spec of each open child the result changes, and take out each child it makes unneeded with `park_child` and say why with `dispatch comment`.
37
39
  - Before you park a child for good (one made unneeded, or parked so its tree can finish), set the `--blocked-by` list of each sibling that waits on it again without it (one call with the rest of its list, or `--clear-blocked-by` when it was the only one), or park that sibling too: a parked child is stopped, not done, and its dependents stay held with no notice. A park followed by `rerun_child` keeps its dependents' links: they wait through the rerun and start when the rerun's merge closes the child.
38
40
  - A released child runs in your tree's admission slot, never its own, and never becomes a root while your tree is live.
39
41
 
40
42
  ## 3. Children complete
41
43
 
42
- No notice marks the last child's close. The root can reach `accepting` before any child merges, but its `sign_off` waits for them (section 6).
44
+ No notice marks the last child's close. The root can reach `accepting` before any child merges; accept its own pull request then (section 6), and its close waits for the rest of the tree.
43
45
 
44
46
  ## 4. Integration verification
45
47
 
46
- - File a final integration child whose acceptance is every parent criterion proven on the default branch your addressing line names (never a hard-coded `main`), in each repository a criterion spans. Release it only after every other child has closed, because it must test a branch that carries their merges; accept the root only after it closes.
48
+ - File a final integration child whose acceptance is every parent criterion proven on the default branch your addressing line names (never a hard-coded `main`), in each repository a criterion spans. Release it at once with `--blocked-by` naming every other child: Legion holds it until the last of them closes and starts it then, so it tests a branch that carries their merges. The root's close waits for it, so the root is done only once it closes. Each child you add later joins its `--blocked-by` list in the same turn it is filed (section 2).
47
49
  - Read its tester evidence, not a child pull request's check status. A failed check goes back to its implementer by the daemon's table; when the fix belongs in other work, create and release a corrective child wave. Never downgrade a parent criterion or carry the failure forward.
48
50
 
49
51
  ## 5. Retro
@@ -59,9 +61,9 @@ The reviewer's `phase-finished` with an `APPROVED` review puts the issue in `acc
59
61
  - the reviewer's approval of that head by SHA (`gh api --paginate repos/<o>/<r>/pulls/<n>/reviews`);
60
62
  - each of the reviewer's prose findings, checked against the code at that head and command output, not against the reviewer's own verdict: no other agent has read that prose.
61
63
 
62
- Accept only when each acceptance line has passing evidence at the approved head, every corrective child and (for a root) the integration child has closed, and no criterion left the tree. Post that evidence as a `dispatch comment`, then `legion({ op: "sign_off", issue: "<KEY>" })`.
64
+ Accept only when each acceptance line of the issue's own pull request has passing evidence at the approved head and no criterion left the tree; a criterion only the tree as a whole meets is the integration child's (section 4), not a reason to hold the root's own pull request. A finding ask on the issue holds the acceptance until it is resolved or carries the controller's reply (`skill://legion-architect/references/acceptance.md`). Post that evidence as a `dispatch comment`, then `legion({ op: "sign_off", issue: "<KEY>" })`.
63
65
 
64
- - `sign_off` works only in `accepting` (`SIGNOFF_OUTSIDE_ACCEPTING`) and is refused 409 `SIGNOFF_CHILD_IN_WORKFLOW` while any issue beneath this one is in the workflow, naming each: wait for the last, or take one out with `park_child`.
66
+ - `sign_off` works only in `accepting` (`SIGNOFF_OUTSIDE_ACCEPTING`). Children still in the workflow do not hold it: a root whose pull request merges waits at its close for the rest of its tree.
65
67
  - When an acceptance check fails: `request_backward_move` with `issue`, `to` (`implementing` or `testing`) and a `reason` naming the failure. It counts a review round.
66
68
  - On every end-game wake (`phase-finished`, `catch-up`, `checks-red`, `review-stuck`), read `gh pr view <n> --json mergeable,mergeStateStatus`, because a `CONFLICTING` pull request gets no CI and no wake. Then, and after acceptance, follow `skill://legion-architect/references/acceptance.md`.
67
69
 
@@ -77,4 +79,5 @@ Handle each delivered wake by its row in `skill://legion-architect/references/wa
77
79
 
78
80
  - `envoy_publish` to the controller (its topic is on your addressing line) a child that serves no criterion of the root, a need for admission slots, and two trees changing the same code, because only it sees other trees. Handle everything else.
79
81
  - A decision that needs the human, yours or a worker's, is a decision block you write, never the worker, because a new version of an approved root spec closes the gate.
82
+ - A clear defect the controller hands you is in code your tree owns, so it is work inside the tree. Add it to an open child whose pull request touches that code. File a child (`dispatch issue --parent`) only when none does. Reply under its evidence comment with the issue that carries it. Change no root spec for it: a child's spec is never gated, and a new root-spec version closes the gate (`skill://legion-architect/references/design-gate.md`, "After approval"). Only a fix that would change the root's Summary, Acceptance or scope is a decision block instead.
80
83
  - A tool a worker cannot get is yours: a pull request changing `sjawhar/legion`'s worker image (`skill://legion-worker/references/tools.md`).
@@ -26,13 +26,25 @@ legion({ op: "sign_off", issue: "LEGION-40" })
26
26
  ```
27
27
 
28
28
  - The issue's Dispatch status stays `needs_review` in `accepting`; `sign_off` moves it to `retro`.
29
- - Only what is beneath the issue counts for `SIGNOFF_CHILD_IN_WORKFLOW`: a child with nothing
30
- beneath it is accepted while its own root runs.
29
+ - A `catch-up` whose `reason` names an issue as waiting for your acceptance is the wake for it: it
30
+ is in `accepting`, and the `phase-finished` notice that moved it there may never have reached you
31
+ (the daemon drops a notice to a failed architect, so a retried one learns of the wait from its
32
+ catch-up alone). Accept it as above.
33
+ - Nothing beneath the issue holds the acceptance: accept a parent's own reviewed head while its
34
+ children still run. A root's close waits for them instead (*The close*, below); a parent that is
35
+ not the root closes at its own merge, and its children carry on under the root.
31
36
  - `request_backward_move` names the issue, because your grant serves the tree; the daemon starts
32
37
  that phase's role with your reason in its task.
33
38
  - `handoff_complete` from you in `accepting` is refused `ACCEPTANCE_IS_SIGN_OFF`. CI red at the head
34
39
  in `accepting` returns the issue to `implementing` by the daemon's table.
35
40
  - No `Production:` line is asked here: the production check is the implementer's, after the close.
41
+ - A finding ask on the issue holds the acceptance: one a worker sent you, or one `dispatch read`
42
+ lists under `Open asks:` whose question opens `Finding from ` or `Clear defect from `
43
+ (`skill://legion-worker/references/findings.md`, "When no controller takes it"). Follow each
44
+ (`dispatch follow --ask <id> --action follow`) and, once it is answered, publish its reference
45
+ to the controller topic. Accept only once each is resolved, or carries the controller's
46
+ `Filed dispatch://`, `Handed dispatch://` or `Not filed:` reply, because a closed issue hides its
47
+ asks from the controller.
36
48
 
37
49
  ## The order after your acceptance
38
50
 
@@ -128,9 +140,10 @@ The merge closes the issue: when GitHub reports the pull request merged while th
128
140
  every member's open production check has closed.
129
141
 
130
142
  Nothing of the production check is yours. Its record lives on the pull request alone, since
131
- Dispatch refuses a write on a closed issue; a defect it finds is a `dispatch ask`, never an issue;
132
- and `read_record` shows a closed issue's open check (`check`: the pull request, the merge commit,
133
- the looks, what woke the last one and when the next is due).
143
+ Dispatch refuses a write on a closed issue. A defect it finds is never an issue the implementer
144
+ files: a clear defect goes to the controller, and any other is a `dispatch ask`. `read_record`
145
+ shows a closed issue's open check (`check`: the pull request, the merge commit, the looks, what
146
+ woke the last one and when the next is due).
134
147
 
135
148
  ## Hand-over at a root's linger
136
149
 
@@ -34,8 +34,9 @@ EOF
34
34
  - `--project` is the issue key's prefix before `-<n>` (`LEGSMOKE-3` → `LEGSMOKE`).
35
35
  - In a root session `$LEGION_ISSUE` is the root (it equals `$LEGION_TREE`): pass it as `--parent`.
36
36
  The daemon makes the sub-issue link from `--parent`.
37
- - Group the returned keys into ordered waves: you release each wave by key with
38
- `release_children`, and a child is inert until then.
37
+ - Order the returned keys into waves with `--blocked-by` links (a later wave's child blocked by the
38
+ children it builds on), then release every child at once with `release_children`: Legion holds a
39
+ released child until its last blocker closes, and a child is inert only until it is released.
39
40
  - Do not pass `--assignee`, because the default keeps the tree's questions in one Inbox: under the
40
41
  shared token a child inherits its parent's assignee (the human who answers the tree's asks), else
41
42
  the project's default assignee, which a person sets on the Settings page; under a personal token
@@ -6,13 +6,13 @@ edit to an approved root spec, and on `design-approved`, `design-changes-request
6
6
 
7
7
  ## Writing the root spec
8
8
 
9
- Specifications written into Dispatch follow `skill://dispatch`'s
10
- [Writing a spec](skill://dispatch/SKILL.md#writing-a-spec). Wave releases, child closures and your
9
+ Specifications written into Dispatch follow
10
+ [`dispatch-writing-specs`](skill://dispatch-writing-specs/SKILL.md#the-outline). Wave releases, child closures and your
11
11
  own status are visible from the issue tree and the handoffs; do not narrate them into the spec or a
12
12
  `dispatch message`.
13
13
 
14
14
  Extend the primary document in place: a new version adds only the evidence each decision needs and
15
- what the human decides, each as a [decision block](skill://dispatch/SKILL.md#decision-blocks).
15
+ what the human decides, each as a [decision block](skill://dispatch/SKILL.md#asks-and-ask-blocks).
16
16
  Never post a second "spec" artifact beside it: `dispatch artifact` with the primary document's name
17
17
  replaces the human's document.
18
18
 
@@ -37,22 +37,27 @@ When the gate is armed, run this exact sequence before the tree's work starts:
37
37
  ```
38
38
 
39
39
  2. Settle every decision block as
40
- [Approval of a spec](skill://dispatch/SKILL.md#approval-of-a-spec) says;
40
+ [Approval](skill://dispatch-writing-specs/SKILL.md#approval) says;
41
41
  `dispatch request-approval` refuses while one is open. Each answer reaches you, since you follow
42
42
  every ask you open.
43
- 3. Run `task(agent="plan-gap-analyst")` with the current root spec, the code and command output it
44
- relies on, and the human's words; resolve every finding in the root spec.
43
+ 3. Before every approval request, give two fresh reviewers the current root spec, the code and
44
+ command output it relies on, and the human's words: `task(agent="plan-gap-analyst")` finds its
45
+ gaps, and `task(agent="plan-reviewer")`, told the document is a spec, checks each factual claim
46
+ against the code, the docs or a read-only command it runs. Resolve every finding in the root
47
+ spec. Check with a command each claim either reviewer marks unverified: fix it when it is
48
+ false, or take it out.
45
49
  4. Request approval only once the human has agreed to every point in the spec, because the human
46
50
  approves what they already agreed to and a point new in the request has no decision block for
47
51
  them to answer: give such a point its own decision block first, or take it out of the spec.
48
52
 
49
53
  ```bash
50
- dispatch request-approval --issue <root issue> --summary '<what the human is approving>'
54
+ dispatch request-approval --issue <root issue> --summary '<what the human is approving> Reviews: <gap result>, <claim result>.'
51
55
  ```
52
56
 
53
- `--summary` says in one to three sentences what the human is approving and nothing else: no
54
- commentary and no open question. The primary document is the default; the command prints
55
- `Approval requested for spec.md (document id <UUID>) at version <N> (ask <id>)`.
57
+ `--summary` says in one to three sentences what the human is approving and nothing else (no
58
+ commentary and no open question), then one sentence with both reviews' results, for example
59
+ `Reviews: no open gap, 14 of 14 claims verified.` The primary document is the default; the
60
+ command prints `Approval requested for spec.md (document id <UUID>) at version <N> (ask <id>)`.
56
61
  5. Register that document version with the daemon:
57
62
 
58
63
  ```ts
@@ -81,13 +86,30 @@ Facts about the request:
81
86
  again to hand the same request back at the latest version.
82
87
  - If the output reads `spec.md (document id <UUID>) is already approved at version <N>`, still call
83
88
  `register_gate` with that id and version: the daemon reads the approval from Dispatch as it
84
- registers, opens the gate and delivers `design-approved` at once. The same read covers a human
85
- who answers between your two calls. You never approve anything yourself.
86
-
87
- Then end your turn. Release no wave until a delivered wake shows `design-approved` on the root. On
88
- `design-changes-requested`: revise the spec as the human's reason asks, run
89
- `task(agent="plan-gap-analyst")` on the new version with the code, command output and the human's
90
- words, resolve every finding, request approval again and end your turn.
89
+ registers, opens the gate and delivers `design-approved` at once, and only once even when the
90
+ approval's own event opened the gate first. The same read covers a human who answers between
91
+ your two calls: a changes request on that version arrives as `design-changes-requested`, once.
92
+ You never approve anything yourself.
93
+ - `register_gate` refused 409 `VERSION_NOT_IN_DISPATCH` means the version you named is above the
94
+ latest version Dispatch holds for that document (the message names both), and a version Dispatch
95
+ never wrote is no registration: the gate is as it was. Read the document's latest version, check
96
+ it is the spec the human is asked to approve, and `register_gate` that version.
97
+
98
+ Then end your turn. The registration hands the spec to the human: when nothing else holds the
99
+ slot, the root returns its admission slot and waits on its design gate (`awaiting_person`), as a
100
+ root question handed to the human does ("Every turn" in `skill://legion-architect/SKILL.md`). The
101
+ human's approval or changes request resumes you, and so does a newer spec version once Dispatch
102
+ shows the request back on your turn. While the root waits on a question instead, the human's
103
+ approval or changes request of the spec answers that wait too, and the resume task says how the
104
+ spec stands. Release no wave until a delivered wake shows `design-approved` on the root, or a
105
+ resume task says its design gate is open: the daemon sends a root waiting on a person no
106
+ `design-approved` notice, and "this resume is your design-approved wake" is that wake. On
107
+ `design-changes-requested`: revise the spec as the human's reason asks, run step 3's two reviews on
108
+ the new version, resolve every finding, request approval again and end your turn. A
109
+ `design-changes-requested` may name a version below the latest, or arrive after another for the
110
+ same version: it is a request the human made that reached the daemon late, and no approval came
111
+ after it. Each request arrives once. The gate is as the newest review left it; still read the
112
+ reason, and answer it in the spec if the latest version does not already.
91
113
 
92
114
  ## After approval
93
115
 
@@ -110,8 +132,9 @@ to the version it writes. Once they have answered:
110
132
  daemon sent opens nothing new. Carry on, and release no wave because of it.
111
133
  - When the answer changes the Summary, the Acceptance or the tree's scope, rewrite that text and
112
134
  repeat steps 3 to 5 on the new version, with a one-sentence `--summary` naming what changed since
113
- the earlier approval (the card shows that approval, `Approved at version N on <date> by <who>.`,
114
- and its `Show diff` control carries the detail). The rewrite closes the gate until they approve;
135
+ the earlier approval, then the reviews' sentence (the card shows that approval, `Approved at
136
+ version N on <date> by <who>.`, and its `Show diff` control carries the detail). The rewrite
137
+ closes the gate until they approve;
115
138
  work the daemon started at the answer keeps running. Release no new wave until the `design-approved`
116
139
  after the rewrite; work already in flight continues. Every merger's `READY` in the tree is
117
140
  refused until a human approves the latest version.
@@ -20,13 +20,13 @@ and 7 (a conflict, the hand-over, the close) is in
20
20
  | --- | --- |
21
21
  | `carried-gate-opened` | Only a root whose catch-up said `carried` gets it. Its `version` and `reason`: a human approved the old root's spec document at `version`, which opened the gate this root carried; the daemon has released any READY it refused and started any child waiting on it. It is not `design-approved`: do not proceed to section 2 or release a wave because of it, and start nothing. |
22
22
  | `child-status` | A child of your tree left the workflow or re-entered it; the reason names the child and its new status. `todo` (a human's move, your `release_children`, or your `rerun_child`) means it runs again under your tree from planning, and the daemon starts it; you start nothing. A child held for a blocker starts the same way once nothing holds it, and the reason, naming it and its root, says what cleared the hold: its last blocker's close, naming the issues it waited on, now done, or a person or you taking its blocked-by links off; you start nothing for it either. `backlog`, `icebox` or `triage` (a human's move, or your `park_child`) means the daemon has suspended its workers, and it advances no further until it is set back to `todo`. What the rest of the tree does is your decision. |
23
- | `child-closed` | Read the child completion and remaining open children. Re-scope open work, park obsolete work for good with `park_child` (first take its link off each sibling that waits on it, or park that sibling too, as section 2 says), and release an appropriate next wave with `release_children`. When a worker waits on this child for a missing surface (see `phase-finished`), tell it to continue with `envoy_publish` to its role topic. The last child's close is not the end-game (section 3). |
23
+ | `child-closed` | Read the child completion and remaining open children. Re-scope open work, park obsolete work for good with `park_child` (first take its link off each sibling that waits on it, or park that sibling too, as section 2 says), and file any new child the result calls for and release it at once with `release_children`, blocked by what it builds on (section 2). When a worker waits on this child for a missing surface (see `phase-finished`), tell it to continue with `envoy_publish` to its role topic. The last child's close is not the end-game (section 3). |
24
24
  | `child-release-stalled` | Its `reason` names a child your `release_children` released while Dispatch already showed it `todo`, and that child's parent, whose release has not reached the daemon after three tries. Read the parent's record with the `legion` tool's `read_record` (`issue` the parent); run `release_children` for the child again once the parent is recorded in your tree, and tell the controller if it never is. |
25
25
  | `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. |
26
- | `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, "After approval" in `skill://legion-architect/references/design-gate.md`), opens nothing new: carry on, and release no wave because of it. |
27
- | `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 "The armed gate" in `skill://legion-architect/references/design-gate.md` says; end your turn; the gate is closed. |
26
+ | `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, "After approval" in `skill://legion-architect/references/design-gate.md`), opens nothing new: carry on, and release no wave because of it. A root that was waiting on a question in `awaiting_person` gets no such notice: the task that resumes it says "Your spec is approved at version N and the design gate is open: this resume is your design-approved wake", and that resume is this wake — proceed to section 2 on it. |
27
+ | `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 "The armed gate" in `skill://legion-architect/references/design-gate.md` says; end your turn; the gate is closed. On a root that was waiting on a question in `awaiting_person`, a review the human gave after the wait began comes in the resume task, not in this notice, whether it answered the wait or came after something else did: the task names the review with its version and reason, unless a later approval superseded it. A `version` below the latest, or a second request for one version, is a request that reached the daemon late: read it as the same section's last paragraph says. Each request arrives once. |
28
28
  | `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 the full condition in "After approval" of `skill://legion-architect/references/design-gate.md`: 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 that section 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. |
29
- | `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 or on a settled head whose base branch requires no check and no workflow, 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, or onto a settled head whose base branch requires no check and no workflow, 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. 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 rounds the cap is for. Each `review_round_cap` notice is a decision you make in the turn it wakes, never one left for the next round to make: read what every counted round found, choose one of the three below, act on it in the same turn, and post it as a `dispatch comment` on the issue naming the rounds you read and the choice. **Narrow**: the change itself is sound but each round finds more around it; tell the implementer and the reviewer (`envoy_publish` to each one's role topic) which acceptance lines the next round answers; a correctness finding is still fixed in this pull request, and only naming, duplication or wording cleanup moves to the `Fast-follow:` line. **Split**: part of the work cannot settle in this pull request. On a child, file that part as a child of this issue's parent, never of this one (a parent waits in `accepting` for every child, and the split part usually builds on this pull request's unmerged code): `dispatch issue --project <project> --parent <parent> --title '<outcome>' --blocked-by <this issue> --spec-file -`. Release it now with `release_children`: Legion holds it on that `--blocked-by` link until this issue closes, and starts it then. On the root, narrow it to what settles here and open a `dispatch ask` for the rest (`skill://legion-worker/references/findings.md`): a person decides whether that becomes an issue. Tell the implementer and the reviewer that this pull request no longer carries it. **Accept the rounds**: each round found less than the one before it, and the last found no defect in the change itself (a stale line, a comment that states an old default); let the loop run and say why in the comment. A later notice is a new decision: accept again only when its round found less than the round you last accepted, and otherwise narrow or split. A finding that changes what the spec accepts is a decision block in the root spec ("After approval" in `skill://legion-architect/references/design-gate.md`), and `dispatch ask` is only for a decision that needs a human's authority; neither replaces the choice. Judge a worker's backward move by the reason that worker gives. A move you ordered for a conflict found before `awaiting_merge` ("A conflicting head" in `skill://legion-architect/references/acceptance.md`) 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. |
29
+ | `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/<issue>/` — handoff-only pushes (`.legion/<issue>/` 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/<issue>/`, 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 or on a settled head whose base branch requires no check and no workflow, 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, or onto a settled head whose base branch requires no check and no workflow, 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. 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 rounds the cap is for. Each `review_round_cap` notice is a decision you make in the turn it wakes, never one left for the next round to make: read what every counted round found, choose one of the three below, act on it in the same turn, and post it as a `dispatch comment` on the issue naming the rounds you read and the choice. **Narrow**: the change itself is sound but each round finds more around it; tell the implementer and the reviewer (`envoy_publish` to each one's role topic) which acceptance lines the next round answers; a correctness finding is still fixed in this pull request, and so is a wording nit or any clear fix in a file it touches, so the `Fast-follow:` line carries only cleanup in files this pull request does not touch. **Split**: part of the work cannot settle in this pull request. On a child, file that part as a child of this issue's parent, never of this one (this issue closes at its own merge, and the split part usually builds on this pull request's unmerged code): `dispatch issue --project <project> --parent <parent> --title '<outcome>' --blocked-by <this issue> --spec-file -`. Release it now with `release_children`: Legion holds it on that `--blocked-by` link until this issue closes, and starts it then. On the root, narrow it to what settles here and open a `dispatch ask` for the rest (`skill://legion-worker/references/findings.md`): a person decides whether that becomes an issue. Tell the implementer and the reviewer that this pull request no longer carries it. **Accept the rounds**: each round found less than the one before it, and the last found no defect in the change itself (a stale line, a comment that states an old default); let the loop run and say why in the comment. A later notice is a new decision: accept again only when its round found less than the round you last accepted, and otherwise narrow or split. A finding that changes what the spec accepts is a decision block in the root spec ("After approval" in `skill://legion-architect/references/design-gate.md`), and `dispatch ask` is only for a decision that needs a human's authority; neither replaces the choice. Judge a worker's backward move by the reason that worker gives. A move you ordered for a conflict found before `awaiting_merge` ("A conflicting head" in `skill://legion-architect/references/acceptance.md`) 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. |
30
30
  | `pr-merged` | The pull request merged and the issue did not close; its `reason` says why. Merged before the issue reached `awaiting_merge`: the workflow runs on, and the merge closes the issue the moment it gets there, your acceptance and retro first. Merged while the rest of the tree still runs: the reason names the pull request and every issue the close waits for, and the root waits in `awaiting_merge`, slot and workers kept, until the last of them is done or parked ("The close" in `skill://legion-architect/references/acceptance.md`). Either way you start nothing and no further notice follows. |
31
31
  | `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. |
32
32
  | `merge-refused` | GitHub refused the daemon's submission of READY's merge in a way a retry would meet again, so it submits that merge no further: ask a person with `dispatch ask` to fix the repository setting or App permission and merge at READY's head (`skill://legion-architect/references/merge-notices.md#merge-refused`). |