@sjawhar/claude-envoy 0.0.0 → 1.0.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 (113) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/.mcp.json +11 -0
  3. package/.omp-plugin/plugin.json +6 -0
  4. package/AGENTS.md +343 -0
  5. package/README.md +639 -0
  6. package/bin/dispatch +6 -0
  7. package/bin/envoy-channel.ts +9 -0
  8. package/bin/envoy-send.ts +33 -0
  9. package/dist/THIRD_PARTY_NOTICES +816 -0
  10. package/dist/dispatch.js +27707 -0
  11. package/dist/envoy-channel.js +57695 -0
  12. package/dist/session-hook.js +26328 -0
  13. package/dist/session-title-hook.js +116 -0
  14. package/hooks/hooks.json +60 -0
  15. package/hooks/session-hook.ts +512 -0
  16. package/hooks/session-title-hook.ts +46 -0
  17. package/legion/.claude-plugin/plugin.json +4 -0
  18. package/legion/agents/deep-worker.md +68 -0
  19. package/legion/agents/oracle.md +35 -0
  20. package/legion/agents/plan-gap-analyst.md +65 -0
  21. package/legion/agents/plan-reviewer.md +104 -0
  22. package/legion/agents/thermonuclear-code-quality.md +30 -0
  23. package/legion/agents/thermonuclear-deep-review.md +30 -0
  24. package/legion/hooks/hooks.json +89 -0
  25. package/legion/skills/ce-simplify-code/LICENSE +21 -0
  26. package/legion/skills/ce-simplify-code/SKILL.md +66 -0
  27. package/legion/skills/ce-simplify-code/references/personas/code-quality-reviewer.md +17 -0
  28. package/legion/skills/ce-simplify-code/references/personas/code-reuse-reviewer.md +7 -0
  29. package/legion/skills/ce-simplify-code/references/personas/efficiency-reviewer.md +11 -0
  30. package/legion/skills/leading-a-work-stream/SKILL.md +96 -0
  31. package/legion/skills/leading-a-work-stream/references/daily-plan.md +8 -0
  32. package/legion/skills/leading-a-work-stream/references/decision-rights.md +6 -0
  33. package/legion/skills/leading-a-work-stream/references/direction-and-coaching.md +13 -0
  34. package/legion/skills/leading-a-work-stream/references/dispatch-upkeep.md +8 -0
  35. package/legion/skills/leading-a-work-stream/references/sources.md +9 -0
  36. package/legion/skills/leading-a-work-stream/references/speed-tick.md +44 -0
  37. package/legion/skills/leading-a-work-stream/references/user-quotes.md +7 -0
  38. package/legion/skills/legion-architect/SKILL.md +86 -0
  39. package/legion/skills/legion-architect/references/acceptance.md +208 -0
  40. package/legion/skills/legion-architect/references/decomposition.md +129 -0
  41. package/legion/skills/legion-architect/references/design-gate.md +206 -0
  42. package/legion/skills/legion-architect/references/merge-notices.md +91 -0
  43. package/legion/skills/legion-architect/references/wake-routing.md +41 -0
  44. package/legion/skills/legion-controller/SKILL.md +151 -0
  45. package/legion/skills/legion-controller/references/admission.md +22 -0
  46. package/legion/skills/legion-controller/references/backlog-stewardship.md +101 -0
  47. package/legion/skills/legion-controller/references/daily-report.md +75 -0
  48. package/legion/skills/legion-controller/references/escalation.md +82 -0
  49. package/legion/skills/legion-controller/references/finding-asks.md +181 -0
  50. package/legion/skills/legion-controller/references/parked-decisions.md +198 -0
  51. package/legion/skills/legion-controller/references/session.md +100 -0
  52. package/legion/skills/legion-controller/references/slack-mentions.md +154 -0
  53. package/legion/skills/legion-controller/references/triage.md +96 -0
  54. package/legion/skills/legion-controller/references/wakes.md +132 -0
  55. package/legion/skills/legion-oracle/SKILL.md +48 -0
  56. package/legion/skills/legion-retro/SKILL.md +112 -0
  57. package/legion/skills/legion-retro/references/learnings.md +60 -0
  58. package/legion/skills/legion-retro/references/pr-body-content.md +56 -0
  59. package/legion/skills/legion-worker/SKILL.md +69 -0
  60. package/legion/skills/legion-worker/references/cleanup-deletion.md +22 -0
  61. package/legion/skills/legion-worker/references/conflicts-and-rewrites.md +164 -0
  62. package/legion/skills/legion-worker/references/default-branch-check.md +53 -0
  63. package/legion/skills/legion-worker/references/findings.md +199 -0
  64. package/legion/skills/legion-worker/references/merge-gate.md +353 -0
  65. package/legion/skills/legion-worker/references/pr-body.md +218 -0
  66. package/legion/skills/legion-worker/references/review-threads.md +77 -0
  67. package/legion/skills/legion-worker/references/systematic-rename.md +19 -0
  68. package/legion/skills/legion-worker/references/tools.md +708 -0
  69. package/legion/skills/thermonuclear-code-quality/LICENSE +21 -0
  70. package/legion/skills/thermonuclear-code-quality/SKILL.md +60 -0
  71. package/legion/skills/thermonuclear-deep-review/LICENSE +21 -0
  72. package/legion/skills/thermonuclear-deep-review/SKILL.md +80 -0
  73. package/package.json +49 -1
  74. package/scripts/build-inputs.txt +84 -0
  75. package/scripts/build.ts +415 -0
  76. package/scripts/check-packed-skills.sh +50 -0
  77. package/scripts/pack-skills.sh +146 -0
  78. package/scripts/smoke-channel.sh +178 -0
  79. package/scripts/smoke-clear-rebind.sh +164 -0
  80. package/scripts/smoke-session-title.sh +245 -0
  81. package/scripts/verify-build.sh +88 -0
  82. package/skills/agent-secrets/SKILL.md +180 -0
  83. package/skills/asd-ste100/LICENSE +21 -0
  84. package/skills/asd-ste100/SKILL.md +140 -0
  85. package/skills/asd-ste100/examples/before-after.md +92 -0
  86. package/skills/asd-ste100/references/writing-rules.md +59 -0
  87. package/skills/dispatch/SKILL.md +89 -0
  88. package/skills/dispatch-first/SKILL.md +46 -0
  89. package/skills/dispatch-writing-specs/SKILL.md +80 -0
  90. package/skills/envoy/SKILL.md +82 -0
  91. package/skills/envoy/references/check-settlement.md +62 -0
  92. package/skills/envoy/references/deliveries.md +67 -0
  93. package/skills/envoy/references/legion.md +14 -0
  94. package/skills/envoy/references/roles.md +12 -0
  95. package/skills/envoy/references/sources.md +41 -0
  96. package/skills/outside-message/SKILL.md +111 -0
  97. package/skills/plain-words/SKILL.md +88 -0
  98. package/src/channel-forwarder.ts +262 -0
  99. package/src/claude-channel.ts +705 -0
  100. package/src/claude-session.ts +38 -0
  101. package/src/envoy-channel-server.ts +2115 -0
  102. package/src/envoy-client.ts +26 -0
  103. package/src/envoy-off.ts +62 -0
  104. package/src/legion-claim.ts +211 -0
  105. package/src/legion-inbox.ts +110 -0
  106. package/src/legion-phase-hook.ts +554 -0
  107. package/src/legion-tool.ts +69 -0
  108. package/src/replay-state.ts +97 -0
  109. package/src/send-arguments.ts +13 -0
  110. package/src/session-identity.ts +165 -0
  111. package/src/session-state.ts +142 -0
  112. package/src/session-title.ts +251 -0
  113. package/src/subscription-topics.ts +16 -0
@@ -0,0 +1,353 @@
1
+ # The merge gate: review, acceptance, retro, READY, the merge, and the production check
2
+
3
+ Part of `skill://legion-worker`. Read it when you are the reviewer submitting a review or an
4
+ approval, the implementer on a look of its closed issue's production check, or the merger
5
+ building READY. Every path it cites is in cybermonklabs/legion.
6
+
7
+ The order, in full: the tester's evidence green → the reviewer's approval of the head → the
8
+ architect's acceptance, in `accepting` → retro → the merger's READY → the merge, which closes the
9
+ issue → the implementer's production check, after the close. Every handoff is a record on the
10
+ Dispatch issue, never a commit, so the head that merges carries none. Retro commits nothing
11
+ (*Retro*, below), so the approved head is the head that merges. READY still lets a commit that
12
+ changes only `docs/solutions/` stand, and a file under `.legion/` that GitHub's compare lists as
13
+ removed, the commit `legion handoffs import` makes to remove the directory where handoffs lived
14
+ before they moved to Dispatch. A conflict-forced merge goes back to the reviewer for a
15
+ confirmation or a new round, as the fingerprint decides (*The reviewer*, below, and
16
+ `skill://legion-worker/references/conflicts-and-rewrites.md`), unless READY refused it, and any
17
+ other change to the head voids it.
18
+
19
+ ## The reviewer
20
+
21
+ - The reviewer reads CI on GitHub and verifies the `Threads` facts and the issue's results there
22
+ and with `dispatch results --issue <issue>` — never from a handoff — then, when the diff
23
+ touches runtime code, runs
24
+ `task(agent="thermonuclear-deep-review")` and
25
+ `task(agent="thermonuclear-code-quality")` once at that head — the head the round reviews —
26
+ waits for each one's result with `wait`, since each runs as a job of its own, and records the
27
+ verdict from what those results say. A result that carries no report, or that names another
28
+ place for it, is a failed run, not a verdict: run that agent again, or read its transcript, and
29
+ record nothing from it until you have the findings text in front of you. Reading the agent's
30
+ diff yourself and recording that in its place is the same as answering the rubric from a bare
31
+ verdict — it is your own reading standing in for a review that did not happen, not the review
32
+ of your own that the round always asks for. When you can do neither — the agent will not run
33
+ again and its transcript holds no findings — that half of the round has no review: tell the
34
+ architect, do not approve, and wait with a `WAITING` line naming what you wait on until it
35
+ answers. The CI it reads is the head's own checks: no handoff is a
36
+ commit, so every push to the branch is work whose head gets GitHub's workflow runs of its own.
37
+ With `<o>/<r>`, `<n>`, `<base>` and `<headRefOid>` from
38
+ `gh pr view <n> --json baseRefName,headRefOid`, two reads. The required set is the
39
+ base branch's rulesets' required checks and its branch protection's, when it has any. Both
40
+ branch endpoints take the base as a URL path, each segment escaped and each `/` kept (a raw `#`
41
+ or `%` reads another branch), built in the same command from the name GitHub returns, never
42
+ pasted or carried over from an earlier command:
43
+
44
+ ```bash
45
+ base=$(gh pr view <n> -R <o>/<r> --json baseRefName -q .baseRefName) && \
46
+ base_path=$(jq -rn --arg b "$base" '$b | split("/") | map(@uri) | join("/")') && \
47
+ echo rulesets: && gh api --paginate "repos/<o>/<r>/rules/branches/$base_path" --jq '.[] | select(.type=="required_status_checks") | .parameters.required_status_checks[].context' && \
48
+ echo protection: && gh api "repos/<o>/<r>/branches/$base_path" --jq '.protection.required_status_checks.checks[].context'
49
+ ```
50
+
51
+ A read GitHub refuses stops the command there, and is reported to the architect, never guessed.
52
+ The head's check-runs
53
+ (`gh api repos/<o>/<r>/commits/<headRefOid>/check-runs --paginate --jq '.check_runs[] | [.name, .status, .conclusion] | @tsv'`):
54
+ every required name present, `completed` and `success` (GitHub counts `neutral` and `skipped`
55
+ as passing for a required check). A required check
56
+ `queued` or `in_progress`: wait. One `completed` as `cancelled`, or absent: re-run that run's
57
+ failed and cancelled jobs, once, then wait — never the whole run, which runs again every job that
58
+ succeeded too. Find the run and job at the head: the head's runs
59
+ (`gh api 'repos/<o>/<r>/actions/runs?head_sha=<headRefOid>&per_page=100' --jq '.workflow_runs[] | [.id, .name, .event, .status, .conclusion] | @tsv'`),
60
+ then each candidate run's jobs
61
+ (`gh api repos/<o>/<r>/actions/runs/<run-id>/jobs --jq '.jobs[] | [.id, .name, .status, .conclusion] | @tsv'`).
62
+ A cancelled job: `gh run rerun <run-id> --failed`, which GitHub applies to the run's failed and
63
+ cancelled jobs and the jobs that depend on them, and to nothing that succeeded. Never
64
+ `--job <job-id>` alone: under a routing workflow, re-running only the final job reads the
65
+ cancelled results again and stays red. GitHub refuses a re-run while an attempt of that run is
66
+ still in progress: wait for it. When no
67
+ run at the head holds the job, or nothing will run it (a check only a commit status reports, a
68
+ workflow another repository defines), tell the architect and do not approve.
69
+ Approval is refused while any `before_merge` check of the issue's own Verification document has no passing result that is current at the head being reviewed: `REQUEST_CHANGES` naming each such check by its block id, and `dispatch results --issue <issue>` is the read that decides it.
70
+ An issue with no Verification document, or whose Verification document holds no `before_merge` check, is a gap you name in the review body, never a review that asks for changes: say which of the two it is, and tell the architect, who writes the checks. Your own findings and the checks that do exist still decide the review, and on an issue that has none the architect's acceptance is the gate.
71
+ A result is current at that head while the head is the head of an open pull request, or the final head of a merged one, attributed to the check's own issue. A child's pull request never makes a root check's result current, and a child never records the result that proves a root's check. A child that carries part of a root's requirement proves it with a check on the child's own Verification document whose `serves` names that requirement, and that result is current at the child's head. A root's own checks are proven at the root's own head, or on the default branch for an `after_merge` check, in the root's last round.
72
+ On a docs-only PR the `Thermo` line still records the simplify pass and the defects it
73
+ reported, and its pair half reads `thermonuclear pair: not run (docs-only)`.
74
+ Submit **one review per round** —
75
+ `REQUEST_CHANGES` when any correctness finding stands, otherwise `APPROVE` of the head you
76
+ reviewed — always named by SHA — carrying every inline comment in that single
77
+ call: `gh api --method POST repos/{owner}/{repo}/pulls/{number}/reviews --input body.json`
78
+ with `commit_id`, `event` (`REQUEST_CHANGES` or `APPROVE`), `body` (with the
79
+ Legion footer), and a `comments[]` array of `{path, line, side, body}`, one entry per
80
+ finding — never one `pr review` call per finding (each submission fires a `pr-review` wake).
81
+ A `COMMENT` decides nothing. After a
82
+ forward merge, compute the fingerprint (*The unchanged-diff check* in
83
+ `skill://legion-worker/references/conflicts-and-rewrites.md`) at the
84
+ `commit_id` of your last submitted review and at the new head. Equal and that review was
85
+ `APPROVE`: submit one more `APPROVE` naming the new head by SHA, its body naming both SHAs
86
+ and the fingerprint — a confirmation, not a round; no thermo pass, no thread pass. Equal and
87
+ that review was `COMMENT` or `REQUEST_CHANGES`: continue that round against the new head;
88
+ nothing restarts. Different, or either run printed no fingerprint: a new round — thermo again,
89
+ one review. A return whose task's `Reason:` names a READY refusal is never a confirmation, even
90
+ after a forward merge, and a no-fix `REQUEST_CHANGES` that answered one is never continued: the round
91
+ after it reviews the refused change in full from the last `APPROVE` (*Retro's commits do not
92
+ void the reviewer's approval* below).
93
+ - Answer every thread you opened, and every thread a bot opened that is none of Legion's role
94
+ Apps, as `skill://legion-worker/references/review-threads.md` says; the same reference says
95
+ when every thread is settled enough to approve, and resolving one never gates your approval.
96
+ - **Fix a prose-only finding yourself** — wording, a count, a tense, a citation — in your own
97
+ commit on the pull request, and list it in your review. Send the work back only for a finding
98
+ that touches code or behaviour. Push the fix **before** you submit the round's review, and
99
+ review the head that push made. A push above the head you approved leaves the approval
100
+ standing for nothing, since any push may change code: the round goes stuck and your architect
101
+ is told (`ApprovalStands` in `packages/daemon/internal/classify/decisions.go`,
102
+ `stuckApprovedOtherCode` in `packages/daemon/internal/workflow/review.go`, and the cases "the
103
+ approval, then a push" and "a push, then the approval of the head before it" in
104
+ `packages/daemon/internal/workflow/review_test.go`). GitHub runs the branch's workflows on that
105
+ push, as on every push. Wait for that head's required checks to be
106
+ green, and approve only then. The daemon sends nothing back for a red at a head the review App
107
+ pushed (`PlannedRed` in `classify/decisions.go`), so your own read is the only one. A red you
108
+ approve over reaches nobody: the tree runs on to the merge, where GitHub holds the pull request
109
+ under the base branch's required checks until someone reads them. A red there is a
110
+ `REQUEST_CHANGES` when the code is at fault, and your own commit to fix when your prose broke
111
+ it. The architect reads your prose commits at its acceptance (*The architect's acceptance*,
112
+ below), and that read is no new round. A round after a READY refusal is the one exception. Its
113
+ approval needs the tester's results to be current at the head, or at an ancestor with only files
114
+ under `.legion/` removed since. So there you fix no prose yourself, and you name each prose
115
+ finding in a `REQUEST_CHANGES`.
116
+
117
+ A reviewer's phase ends with its completion, not with its review. Every round records a handoff
118
+ and takes this order: read CI as above; write the handoff and record it with
119
+ `dispatch handoff-write`; submit the review of the head, by its SHA; then complete. A red at the
120
+ code is a `REQUEST_CHANGES` naming the check, never an approval. A request for changes does not
121
+ wait, since it stands whatever CI says and the issue leaves reviewing with it. The approval waits
122
+ on nothing either: it ends the round whatever CI says at the head it names, since the round reads
123
+ no CI verdict, and a red the daemon reads later — at that head or any above it — is the code's red
124
+ and resumes the implementer from wherever the issue is (reviewing, retro or merging) without the
125
+ reviewer. A head your own push changed is the exception. The daemon marks it a planned red and
126
+ sends nothing back for it, so wait for its checks yourself (*Fix a prose-only finding yourself*,
127
+ above). The daemon moves the issue once both are in — the decision GitHub reports and your
128
+ completion, in either order — so a review posted without a completion leaves the issue in
129
+ reviewing until you finish.
130
+
131
+ ## The architect's acceptance
132
+
133
+ - Between the reviewer's approval and retro the issue sits in `accepting` (Dispatch status
134
+ `needs_review`), where no worker is started: the tree's architect reads the evidence (the
135
+ tester's handoff, `dispatch results --issue <issue>` at the approved head and the reviewer's
136
+ approval of the head by SHA; the daemon lets no child hold it; a parent's waits for its last
137
+ round, `skill://legion-architect`, section 4) and accepts with the
138
+ `legion` tool's `sign_off`, which moves the issue to retro, or sends it back to `implementing`
139
+ or `testing` with `request_backward_move` and a reason, which reaches the started worker's task
140
+ as its `Reason:` line and counts a review round. The acceptance comment names each check with
141
+ its result. An issue with no Verification document, or with no `before_merge` check, reaches
142
+ the architect as a gap the tester and the reviewer named and neither refused, so the
143
+ architect's acceptance is the only gate on it: the acceptance comment names that gap and
144
+ decides there, accepting the issue or sending it back with the checks the architect writes,
145
+ which closes no design gate while dispatch://INFRA-175 has not shipped. The architect also
146
+ reads the reviewer's own prose commits here, with the rest of the evidence, and that read is no
147
+ new round. It does not
148
+ accept while the issue holds a finding ask no controller has taken (`findings.md`, "When no
149
+ controller takes it"). The issue's approval is gated by the `before_merge` checks of its own
150
+ Verification document at its own head, so a child's result against a root's check proves
151
+ nothing for the root: the root's checks are proven at the root's own head, in its last round.
152
+ The acceptance asks for no `after_merge` result: that one is recorded
153
+ after the close (*The production check after the close*, below).
154
+ CI red at the head in `accepting` returns the issue to `implementing` as it does in review. A
155
+ head the review App pushed is the exception: the daemon marks it a planned red and acts on it
156
+ nowhere, and GitHub holds the merge under the base branch's own rules.
157
+
158
+ ## Retro
159
+
160
+ - **Retro commits nothing.** It reads the evidence, writes what the work taught as a
161
+ `dispatch comment` on the issue for the skill librarian, brings the PR body up to date and
162
+ completes (`skill://legion-retro` gives the steps), so the approved head is the head READY
163
+ names. Anything above the approved
164
+ head voids the approval, except the handoff import's removal of `.legion/` files and a commit
165
+ that changes only `docs/solutions/`, which READY still lets through: READY is refused
166
+ `READY_UNREVIEWED_CHANGE`, naming the paths, and the merger tells the architect, who has it send
167
+ the head back to review instead of completing, the move's reason naming the refusal's code and
168
+ what it found. `READY_UNREVIEWED_CHANGE` has more causes than a path outside retro's own; every
169
+ one of them sends the head back to review and none is an error to retry, and the complete list,
170
+ with each remedy, is the merger's own role prompt part.
171
+ A conflict merge pushed above the approved head with no review round after it
172
+ brings the base's paths above that head, so READY refuses it the same way; one sent back through
173
+ `implementing` by the conflict procedure gets its confirmation before READY runs. A READY
174
+ refusal's return reaches the reviewer as a new round, never a fingerprint confirmation. Retro
175
+ removes nothing.
176
+ - **Retro brings the PR body's path-derived content up to date before it completes.** Whatever the
177
+ repository's instructions derive from the pull request's changed paths (a checklist named for
178
+ each class of path, read by a required check), retro recomputes for the whole diff at its head
179
+ and writes into the live body before it completes (`skill://legion-retro`), since the merger
180
+ reports a stale body rather than rewriting it. A body edit changes no commit, so the approval
181
+ stands.
182
+
183
+ ## The merger
184
+
185
+ - The merger resolves no review thread: the reviewer's approval already judged them, and READY
186
+ requires no thread state beyond it. It quotes what sits above the approved head with
187
+ `cd -- "$LEGION_WORKSPACE" && jj -R "$LEGION_WORKSPACE" git fetch && jj -R
188
+ "$LEGION_WORKSPACE" diff --from <approved-sha> --to <tip-sha> --summary` in READY; the daemon,
189
+ not the merger, holds those commits to retro's: READY reads GitHub's compare of the round's
190
+ approved head with READY's head and refuses any other path (`READY_UNREVIEWED_CHANGE`), and a
191
+ round with no recorded approval (`READY_NOT_APPROVED`).
192
+ *The READY packet* is
193
+ `READY #<n> at <current sha> (approved at <approved sha>) for <KEY> (<pr url>)`
194
+ (the shape `packages/daemon/internal/prompts/roles/merger.md` defines), then the PR body's
195
+ `Outcome:` line and its `Not proven / risk:` value — every bullet under that label joined with
196
+ `; ` on the one READY line, or `none` — quoted from the `## For the reviewer` block at that same
197
+ head (or one line saying the body carries no brief — the packet still goes out), then the
198
+ `--summary` output and the PR body's gate facts. The READY packet names each `before_merge`
199
+ check with its latest result, as `dispatch results --issue <issue>` prints it; a check with no
200
+ current passing result is reported to the architect instead of completing.
201
+ - READY is `handoff_complete` with `ready: true` and the packet as its `summary`; the merger runs
202
+ no pre-flight of its own, and its completion reports the commit the workspace stands on. READY's
203
+ checks run in the daemon, which reads the pull request's head on GitHub and refuses, before
204
+ recording anything, on each ground the merger's role prompt names in its `Go daemon workflow`
205
+ part, by its code and with its remedy. That part is the one complete list of READY's refusals. A
206
+ refusal records nothing; the merger reports it to the architect unless it says to complete
207
+ again, and never pushes a commit to make CI run. On success the daemon posts the packet as a
208
+ `dispatch message` on the issue, publishes it to the project's merge queue role when one is set,
209
+ and says on the issue when that role has no live holder; the answer's `note` says when READY was
210
+ published on a pull request a person already merged, whose head can no longer change, or carries
211
+ the by-hand note of a pull request a person merges.
212
+ - **The daemon submits the merge the moment READY is accepted, unless the answer says a person
213
+ merges it.** It queues a `ready_merge` outbox row for the head READY named, and the row, as the
214
+ implement App, reads GitHub and then the record: while the issue still awaits that READY head, a
215
+ base with a merge queue gets the pull request enqueued once GitHub reports it mergeable now
216
+ (`CLEAN`, `UNSTABLE` or `HAS_HOOKS`); otherwise a pull request GitHub reports mergeable now is
217
+ squash-merged, and one in a repository that allows auto-merge is armed. Every request carries
218
+ READY's head as GitHub's expected head, so GitHub refuses it once the head has moved. On a
219
+ merge-queue base the row never arms auto-merge: while a required check still runs, or anything
220
+ else keeps GitHub from reporting the pull request mergeable, it waits, reading GitHub again on
221
+ the outbox's backoff, and enters the queue once GitHub does. In a repository that allows neither a
222
+ merge queue nor auto-merge, the row waits the same way until GitHub reports the pull request
223
+ mergeable — a required check finishing, a required review a person gives — and then merges it. An
224
+ arm or a queue entry is not the end: the row keeps reading GitHub until GitHub reports the pull
225
+ request merged at READY's head. Once it has seen the arm or entry, it never submits that head
226
+ again after someone else removes it: the merge queue taking the pull request out because the merge
227
+ failed (GitHub's reason `failed_checks`, or an unexplained reason with a check that failed, timed
228
+ out, failed to start, needed action or went stale on the commit the queue built for its
229
+ `merge_group` CI) sends the issue back to `implementing`, the implementer's task naming each
230
+ failing check and its run, as a red head does; any other removal (a person dequeues it,
231
+ cancelling its runs, or turns auto-merge off, GitHub turns it off, the queue finds a conflict)
232
+ ends the row and is told to the architect once
233
+ (`merge-removed`). Two removals are submitted again: the implement App's own disarm sent before
234
+ READY that GitHub applied late (auto-merge `manually_disabled`, or a `manual` dequeue, by that
235
+ App), and auto-merge a close turned off, which the reopen at READY's head undid. GitHub's
236
+ rules decide each answer: the daemon bypasses
237
+ none, and a person may merge it first. A refusal a retry would meet again (squash merges disabled,
238
+ a permission the App lacks) ends the row and is told to the architect once (`merge-refused`), with
239
+ GitHub's message. While the record still awaits READY's head, GitHub showing the pull request
240
+ closed or at another head is a webhook not yet applied, so the row waits for the two to agree.
241
+ Only once GitHub's last change to the pull request is more than 10 minutes old, however long the
242
+ row waited before, does the row end and tell the architect once (`merge-stalled`). A merge the
243
+ daemon submitted that GitHub has not completed within an hour of READY's acceptance tells the
244
+ issue's architect once (`merge-waiting`) and goes on waiting: nothing is withdrawn, the merge
245
+ stands, the issue stays in `awaiting_merge`, and the architect reads the pull request for what
246
+ GitHub waits on — a required check that never ran or failed, a review only a person can give, a
247
+ queue that has not landed it — and asks a person for what no worker can do. A reopen at
248
+ READY's head reuses the row, starts it over as though nothing had been armed, and takes it from a
249
+ run that read the record before the reopen. Any other failure retries.
250
+ No role runs `gh pr merge`. When the answer's `note` begins `MANUAL_MERGE_REQUIRED:` (the pull
251
+ request touches a path the project's `merge.by_hand` names), READY stands but the daemon submits
252
+ nothing: the merger tells the architect the note and the head, and a person merges under the
253
+ repository's rules. While an earlier auto-merge disarm for that pull request remains unfinished,
254
+ a by-hand READY refuses `READY_DISARM_PENDING`; retry it once the disarm finishes, so a stale
255
+ ordinary arm cannot merge the person-only head. Ordinary READY does not wait for the disarm. The
256
+ daemon tells that READY with the note at its head and the packet's `Merge:` line replaced, so the
257
+ issue and the merge queue role are never asked to arm it. A READY the design gate refused is
258
+ submitted by the daemon when the approval that opens the gate moves the issue to
259
+ `awaiting_merge`. A push that moves the head past a READY the gate holds voids it before then:
260
+ the architect is told `READY_HEAD_MOVED` and has the merger build a new READY at the new head.
261
+ The packet's second line records the step,
262
+ `Merge: the daemon submits pull request #<n> at <head> once READY is accepted`.
263
+ - **The daemon disarms a merge no READY covers.** Auto-merge stays enabled across pushes, and the
264
+ expected head is checked only when it is enabled, so the daemon itself disables the pull
265
+ request's auto-merge and takes it out of a merge queue, as the implement App, on any push or
266
+ reopen but one landing on an awaiting READY's head, when READY is withdrawn (a push or reopen
267
+ moved the head past it, its CI turned red, or it conflicts with its base, each of which sends the
268
+ issue back to `implementing`), when a child is set back to `todo`, and when the issue leaves the
269
+ workflow. A by-hand READY covers no arm, so whoever arms it is undone. A `ready_merge` row whose
270
+ READY the record has left, or whose pull request the record holds closed, submits nothing; a pull
271
+ request reopened at an awaiting READY's head gets that head's merge submitted again. No role runs
272
+ a disarm.
273
+
274
+ ## The production check after the close
275
+
276
+ - **The merge closes the issue; the production check is the implementer's work after the close.**
277
+ When the pull request merges, the daemon writes `done` and, in the implementer's session, still
278
+ live, hands it the check task. On a root whose tree still runs the close, and so the check task,
279
+ comes later: the merge is recorded, the root waits in `awaiting_merge` until the last other
280
+ issue of its tree is done or parked, and the check opens with that close. Its first line is
281
+ `Production check of <KEY>: <title>.`, and it names the repository, the pull request, the merge
282
+ commit, the look's number, what woke the look (`the merge`, for the first) and whether it is the
283
+ last. A resumed session tells the check task
284
+ from its last phase task by that first line. The check carries no phase and no handoff: a look
285
+ ends with `handoff_complete` carrying a `verdict` and a `summary`, no commit, and the daemon
286
+ refuses a report on an issue with no open check (`CHECK_NOT_OPEN`), on a look already ended
287
+ (`CHECK_LOOK_NOT_OPEN`), or with no verdict of `pass`, `pending` or `fail`
288
+ (`CHECK_VERDICT_REQUIRED`).
289
+ - **Each look does three things.** Do what the deployment instructions say to reach the deploy:
290
+ when they name an agent or role for it, `envoy_publish` the merge commit to that role's topic
291
+ with `expects_reply: none`, and await no reply. Read whether production carries the merge. Then
292
+ report one of three outcomes:
293
+ - `pass`, once you drove the changed path in production through the user's own access path and
294
+ recorded the result: `dispatch result` against the issue's `after_merge` check, at the merge
295
+ commit, its `observed` ending `woken by <event>`, with the printed line in the PR body's
296
+ `Checks` block and one pull-request comment carrying the Legion footer. A closed issue takes a
297
+ result for an `after_merge` or `default_branch` check and refuses every other write. A staging
298
+ pass is not this, since a
299
+ staging gate does not run every resource production does.
300
+ - `pending`, when production does not carry the merge yet (a shared profile still holding the
301
+ previous release, a daemon still running the previous commit, a deploy nobody has run): the
302
+ summary names what is missing, nothing is recorded, and the check's line in the body stays at
303
+ `- Check <block id> (after_merge): not yet run`.
304
+ - `fail`, for a defect: record the failing result with `dispatch result --verdict fail`, file no
305
+ issue, and take the path
306
+ `skill://legion-worker/references/findings.md` gives it. A defect with a clear fix goes to the
307
+ controller topic, with its evidence comment on the controller's report issue. A defect that
308
+ needs a decision is a `dispatch ask` on the report issue, and you publish its reference to the
309
+ controller topic. Either names this issue, the pull request, the merge commit, what you drove
310
+ and what failed. Name the message or the ask (`dispatch://<REPORT KEY>/ask/<id>`) in the
311
+ result's `observed` and in the summary.
312
+ - **Numbers the daemon holds are read with the `legion` tool.** Where the verdict rests on what a
313
+ deployment's idle release has done, `read_release_records` answers a window of the daemon's own
314
+ records of its releases, resumes and holds: its one argument `since` is the RFC 3339 instant
315
+ the window starts at, and the tool's own description says what the answer carries. It reads
316
+ them with this session's own claim, so there is no credential to fetch and none on disk.
317
+ - **Nothing waits in the session for a deploy.** A `pending` ends the look. Where no wake is
318
+ queued yet, the daemon suspends your claim with its session kept, and the issue's Sandbox goes
319
+ with its pod and disk; where a wake arrived while the look was open, the next look starts at once
320
+ on the same pod. Either way the daemon wakes the check (after a suspension a new pod comes back
321
+ on a fresh disk, and your session resumes with a new check task) on Dispatch's
322
+ `issue.deployed` event for the pull request; when the project's `legion.yaml` names the
323
+ repository's deploy workflow (`projects.<KEY>.deploys`), at each completed run of that workflow
324
+ on the default branch whose named step (such as `Apply`) succeeded after the merge, once per such
325
+ job; or, for `cybermonklabs/legion`, on a Legion daemon's boot on a build containing the merge, on
326
+ Dispatch's `server.started` announcing that every server process serves such a build, or on the
327
+ build the daemon read from Dispatch at its boot. The woken look's task names the event
328
+ (`Dispatch's issue.deployed: run <id> completed <t>`,
329
+ `the deploy workflow's run: <repo> <workflow> run <id> attempt <n>, job <job name>: <step> succeeded at <t>`,
330
+ `the Legion daemon's boot on build <sha>`, `Dispatch serving build <sha> on every server process`,
331
+ `Dispatch's build <sha>`), and the result you record names it too, so the pull request carries
332
+ the cause. Never poll for the deploy, never wait on a reply, and never ask anyone for approval
333
+ to deploy. Open a `dispatch ask` to a person only when the instructions name nobody for that
334
+ deploy; it starts with the production gap and why it matters, then names the required install or
335
+ restart step, its risk, and outcome-named options, and the look still ends `pending`.
336
+ - **The bounds.** A look is bounded at 2 hours: one that reports nothing ends as a `pending`
337
+ would. The whole check is bounded by the project's `production_check_hours` (336, 14 days, by
338
+ default) from the close, and the wake at that bound is the last look, told so in its task
339
+ (`the bound: production did not carry the merge within <N days>`). A `pass` or `fail` there
340
+ closes the check as any look's would; a `pending` closes it as not run, and before reporting it
341
+ you write on the pull request, in the check's line and a comment, that the check did not
342
+ run because production did not carry the merge within the bound.
343
+ - **The record lives on the pull request and in the result.** Dispatch refuses a message, a
344
+ comment or an ask on a closed issue (`ISSUE_CLOSED`) and takes only a result for an
345
+ `after_merge` or `default_branch` check, so the deployment instructions' "on the pull request
346
+ and the issue" is the pull request and that result. A defect reaches Dispatch by the two paths above:
347
+ a clear defect as the message to the controller, which gives it to the tree that owns that code,
348
+ and any other as the ask on the
349
+ controller's report issue. The architect accepted the issue before the merge and is asked
350
+ nothing after it. `pass` or
351
+ `fail` closes the check: your claim is retired and the issue's Sandbox goes with its pod and
352
+ disk, for a root as for a child. Neither ending retires or suspends anything of an issue back in
353
+ the workflow (a root reopened inside its linger): its claim and pod are the new run's.
@@ -0,0 +1,218 @@
1
+ # PR body, recorded results, and the simplify pass
2
+
3
+ Part of `skill://legion-worker`. Read it before you write or edit any line of the pull request
4
+ body, record a result against one of the issue's checks, read another phase's results, or run the
5
+ simplify pass. Every path it cites is in cybermonklabs/legion.
6
+
7
+ ## The pull request body template
8
+
9
+ The implementer writes the PR body from this template from the moment the PR opens, and every
10
+ later phase keeps it current rather than replacing it:
11
+
12
+ ```
13
+ ## For the reviewer
14
+
15
+ **Outcome:** <one sentence a user of this repository would recognise: what someone can now do, or what stops going wrong>
16
+ **Why:** <the problem, one or two sentences, ending with the Dispatch key in parentheses — the key only, never a URL>
17
+ **Change:**
18
+ - <two to five bullets, each one behaviour a user or operator meets, never a file name>
19
+ **Look at first:** <one to three `path:line` places where a wrong decision would hurt> (the reviewer writes this line)
20
+ **Proven by:** <the surface and the run of the check the change turns on, one line>
21
+ **Not proven / risk:**
22
+ - <one line per claim recorded as unproven before READY>, or the single word `none` (the reviewer writes this line; `none` is invalid while such a claim stands)
23
+ **Size:** <files changed, +added/−removed>
24
+
25
+ ## Verification
26
+
27
+ **Threads:** <n> resolved, 0 unresolved. Each answered and resolved individually by the implementer, the pull request's author, never in bulk (the reviewer names the bot threads it accepted; it resolves none itself):
28
+ - Thread <node id>: fixed in <commit-sha> — <one line>; resolved at <head-sha>.
29
+ - Thread <node id>: not a defect — <reason>; resolved at <head-sha>.
30
+ - Thread <node id>: accepted by the reviewer — <its reason, one line>; resolved at <head-sha>.
31
+ - Thread <node id>: still open — <what remains>; unresolved at <head-sha>.
32
+
33
+ **Thermo:** `ce-simplify-code` once at <head-sha>: <0 applied | applied → new head <sha>>; defects reported: <none | <n>, fixed in <sha>>; thermonuclear pair at the reviewed head <sha>:
34
+ <verdict>. (on a docs-only PR the simplify half and the defects are recorded as on any other diff, and the pair half reads `thermonuclear pair: not run (docs-only)`)
35
+
36
+ **Checks:** one line per `check` block of the issue's Verification document, in the document's
37
+ order, each the line `dispatch result` printed when the result was recorded:
38
+ - Check <block id> (<when>): <pass|fail> at <the commit's first 12 characters>, recorded by <role>. <the check's first words>
39
+ - Check <block id> (after_merge): not yet run
40
+
41
+ **Fast-follow:** "none", or one named cleanup item in a file this pull request does not touch, and where it will land.
42
+
43
+ **Chain:** stacked on <base bookmark> frozen at <sha> / not stacked.
44
+ ```
45
+
46
+ ## Never waiting on CI
47
+
48
+ The implementer runs the repository's fast local checks for the paths it changed before the push,
49
+ then pushes and completes. It never waits for, watches or polls the pull request's remote CI
50
+ (`gh run watch`, `gh pr checks --watch`, `sleep` around `gh run view`) and never sleeps in a loop
51
+ (the step's spaced reads of the pull request's head after a push are the one sleep this rule
52
+ allows, and they read no check; `skill://legion-worker`, *Every role pushes its own commits*,
53
+ gives them).
54
+ Under the Go daemon a check or workflow the base branch requires that settles red on the head,
55
+ before the completion or after it, sends the work back to `implementing` with the failing checks
56
+ named, until `max_fix_attempts` is spent, when the architect decides. The one CI result an implementer waits for is a re-run: when its task names a red that
57
+ failed on its own, it re-runs the failed jobs once (`gh run rerun <run-id> --failed`) and completes once
58
+ the re-run settles green, woken by the pull request's checks event (`skill://envoy`, *Wait for
59
+ CI or a merge*: subscribe, then end the turn), never by a sleep loop. A completion while that red
60
+ still stands is sent back, at once for a required check and at the daemon's next read of the runs
61
+ (within two minutes) for a required workflow.
62
+
63
+ A pull-request body edit re-runs a check that judges the body at once, on the head as it is. While
64
+ the pull request conflicts with its base (GitHub shows it `CONFLICTING`), no workflow triggered
65
+ `on: pull_request` runs for any of its activity types, so a body edit re-judges nothing there; a
66
+ push cures it only once the pull request is mergeable, so the implementer forward-merges a
67
+ conflicting one first (*Reintegrating the base* in
68
+ `skill://legion-worker/references/conflicts-and-rewrites.md`).
69
+
70
+ ## The brief for the human
71
+
72
+ `## For the reviewer` is written for the person who merges; `## Verification` below it stays the
73
+ ledger the reviewer and merger check against GitHub. The implementer writes `Outcome`, `Why`,
74
+ `Change`, `Proven by`, and `Size` when the pull request opens, and keeps them true after every
75
+ push; `Outcome` is a sentence a user of the repository would recognise, never "fix bug" or a file
76
+ name, and `Why` ends with the Dispatch key, never a URL. The reviewer writes `Look at first` and
77
+ `Not proven / risk` at each round, into the live body (`gh api
78
+ repos/{owner}/{repo}/pulls/{number} --jq .body`, edit, then `--method PATCH ... -F body=@body.md`);
79
+ `Not proven / risk` copies every claim recorded as unproven before READY — the tester's
80
+ `failures`, the reviewer's own review, any proof-check comment already on the pull request —
81
+ word for word, and `none` is a finding while one stands. The merger quotes `Outcome` and
82
+ `Not proven / risk` from the body at the head its READY packet names
83
+ (*The READY packet* in `skill://legion-worker/references/merge-gate.md`); a stale `Outcome` that no
84
+ longer describes the diff is a finding against the implementer, not a line the merger rewrites.
85
+
86
+ ## What a result is
87
+
88
+ **A check** is a `check` block of the issue's Verification document (`verification.md`). It names
89
+ the requirements it serves, where a person reaches the change (`surface`: `browser`, `cli` or
90
+ `api`), what to `run`, `when` it runs (`before_merge`, `after_merge` or `default_branch`) and its
91
+ `negative_control`. The architect writes the checks with the spec; nothing else decides what must
92
+ be proved.
93
+
94
+ **A result** is one run of one check, recorded with
95
+ `dispatch result --issue <issue> --check <block id> --role <your role> --verdict pass --commit <sha>`,
96
+ with `--surface`, `--run`, `--observed` and `--negative-control` as the check asks for them. The
97
+ command prints the pull request body's line for it, and that line goes into the body unchanged.
98
+ The surface is **production-like** — the repository's real-process test harness and fixtures, a
99
+ sandbox repository, a real browser, a devN stack, staging, or a local stack with real migrations,
100
+ one that has the resource the change touches — and `--run` or `--observed` carries a **link** to
101
+ that run, screenshot, or e2e; human review does not replace user-facing verification, and a green
102
+ unit suite is not it. A unit or integration test is a regression lock, never the result of a
103
+ check. The agent that develops the change records its results this way before the merge, and
104
+ whatever blocks a check is fixed, not skipped (*When no surface reaches the changed path*, below).
105
+
106
+ **A check that cannot fail is not a result.** Before a check counts as evidence, show it
107
+ failing: the negative control is that demonstration, run on the same command with a deliberately
108
+ wrong input or call. A check whose pass survives empty output, a missing file or the wrong head
109
+ proves nothing about the change. A documented procedure counts only when it ran: reading it, or
110
+ reading the document that describes it, is not a run, and a procedure no surface available to
111
+ you can run is reported under *When no surface reaches the changed path* below, never passed.
112
+
113
+ **A result is current** while its commit is still the head of an open pull request of the check's
114
+ issue, or the final head of a merged one, and the check's words have not changed since; an
115
+ `after_merge` or `default_branch` result is current at a commit the default branch carries. A push
116
+ makes every result at the old head older, with no Dispatch write of anyone's, so each check is
117
+ recorded again at the new head. `dispatch results --issue <issue>` prints each check with its
118
+ latest result and whether that result is current, and `dispatch read --issue <issue>` names each
119
+ requirement of the spec no check serves.
120
+
121
+ **An issue is proved by its own checks.** Its approval is gated by the `before_merge` checks of
122
+ its own Verification document, read at its own head, so a child's pull request never makes a
123
+ root check's result current and a child never records the result that proves a root's check. A
124
+ child that carries part of a root's requirement proves it with a check on the child's own
125
+ Verification document whose `serves` names that requirement. A root's own checks are proven at
126
+ the root's own head, or on the default branch for an `after_merge` check, in the root's last
127
+ round.
128
+
129
+ **An issue with no `before_merge` check is a named gap.** An issue with no Verification document,
130
+ or with one that holds no `before_merge` check, has no evidence of its own. The tester names that
131
+ gap in its handoff and the reviewer in its review, and neither one sends the issue back for it;
132
+ both tell the architect, who writes the checks, and the architect's acceptance comment names the
133
+ gap and decides there, which is the only gate on such an issue.
134
+
135
+ ## The rules every phase's evidence follows
136
+
137
+ - **The implementer records a result for every `before_merge` check before its phase completes,
138
+ and writes the `Checks` lines when the pull request opens.**
139
+ A check with no surface yet is the report of *When no surface reaches the changed path* below,
140
+ never a check left unrecorded. The results are on the Dispatch issue, and the lines are in the
141
+ PR body, because the reviewer and the merger verify facts on GitHub and never from a handoff.
142
+ The `implement` handoff carries no results: Dispatch holds them, and the tester reads them with
143
+ `dispatch results`.
144
+ - **The tester judges the implementer's results and records its own.** It re-runs the
145
+ implementer's command or drives the same surface independently, and records the verdict in
146
+ its `test` handoff as `implementerProof` (`{verdict, how}`). The tester runs the
147
+ application, not CI again. Try to break the changed surface — wrong and boundary inputs, the
148
+ second and the concurrent run, the party it must refuse — judge whether the implementer's tests
149
+ would catch the ways it breaks, writing the red test for one that none would, and
150
+ read CI on GitHub at the head you are judging for everything static: lint, types and the unit
151
+ and integration suites are CI's, read there and recorded for no later step, and no CI lane is
152
+ rerun as evidence. A lane GitHub shows `queued` or `in progress` is read as such: the tester
153
+ never waits for it, since a required red that settles sends the work back from `testing` and
154
+ the reviewer reads the head's checks before it approves.
155
+ A `before_merge` check the implementer left with no current result is a test failure, not a gap
156
+ for the tester to fill: record it in `failures` (each `{check, evidence}`, `check` the block id)
157
+ with `implementerProof.verdict: "rejected"`, complete the phase with
158
+ `verdict: "fail"`, and the daemon returns the issue to the implementer — the agent that developed the change owns
159
+ proving it (a rejected verdict, or `failed > 0`, always comes with the failure recorded in
160
+ `failures`). Otherwise record your own result for each `before_merge` check before you complete,
161
+ and put each printed line in the body. A code path whose first execution is after merge — a
162
+ deploy workflow's inline step, a post-merge helper, a production-only resource — is a check
163
+ marked `after_merge`, recorded after the merge, unless the implementer can execute it against a
164
+ devN stack before then; if no surface can reach it, the
165
+ tester names that missing surface as the blocker instead of passing the phase. Environment or
166
+ secret-scrub evidence (e.g. "`LEGION_*`/`DISPATCH_*`/`ENVOY_*` unset") is recorded once, in
167
+ its `test` handoff, and only when a check calls for it — never
168
+ re-pasted into the PR body each round. After a forward merge, compute the
169
+ fingerprint (*The unchanged-diff check* in
170
+ `skill://legion-worker/references/conflicts-and-rewrites.md`) at the commit your results name
171
+ and at the new head. Equal: re-run only the
172
+ bare gates — the repository's CI green at the new head and its smoke check — and record each
173
+ check again at the new head, its `--observed` ending
174
+ `forward-merge re-check <old-sha> → <new-sha>: fingerprint unchanged, bare gates only, class search of earlier findings clean`. A search that finds an instance is a failure, not a re-check: record it under `failures` and run a full test round. The
175
+ real-surface verification is not repeated, except in a parent's last round, which the architect
176
+ or the implementer's forward-merge comment names to you: then run a full test round. Different:
177
+ a full test round.
178
+ - **The implementer runs `skill://ce-simplify-code` once per pull request, in its first
179
+ implementing round, after its own results and before it completes that round,
180
+ whatever the diff touches, a docs-only diff included.** The daemon starts no implementing round
181
+ between a clean review and the approval, so this is the one slot before the tester and the
182
+ reviewer read the head; a later round answering a review runs no second pass. It is scoped to
183
+ the pull request's own diff at that head: nothing applied leaves the head as it is; applied →
184
+ the implementer re-runs the repository's checks and the issue's own checks on the applied head
185
+ for the surface the simplify diff touched, since a refactor that "preserves behaviour" is a
186
+ claim until it is executed, and records each result at that head before it completes.
187
+ That cost is why 0-applied is the expected outcome and a pass that applies is spent sparingly.
188
+ The pass covers every file of the diff, workflow YAML and documentation with the code, and a
189
+ defect it reports is fixed outside the pass with the results recorded again, never dropped as
190
+ out of scope; the `Thermo` line's `defects reported` half names how many and the commit that
191
+ fixed them, so a head that moved for a reported defect is not recorded as `0 applied` alone.
192
+ The reviewer's pair runs at the head each round reviews, when the diff touches runtime code.
193
+ Record both in the `Thermo` line.
194
+ - **No deferrals** is the body's rule (*PR body, review, and the merge gate* in
195
+ `skill://legion-worker`): a wording nit, and any clear fix in a file this pull request touches,
196
+ is made in the running round, because a later round costs a CI pass and a re-read of the whole
197
+ change (the operator's answer on that case: fix it while you are there, and defer no fix to
198
+ another issue). The `Fast-follow:` line reads
199
+ `none`, or names only cleanup in files this pull request does not touch.
200
+ A base frozen for others to stack on is never rewritten (*Rewriting pushed commits* in
201
+ `skill://legion-worker/references/conflicts-and-rewrites.md`); the `Chain` line records it.
202
+ - **GitHub refuses a pull request body over 65,536 characters.** Each verification round links its
203
+ evidence (the run, the comment) rather than inlining it once the body passes about 48,000
204
+ characters; a `Check` line keeps its evidence in the result on Dispatch and links the rest.
205
+
206
+ ## When no surface reaches the changed path
207
+
208
+ No surface reaches the changed path is a report to the architect, never a reason to complete the phase.
209
+ Say which surface is missing and what it would have to do — a rig that can spawn the role, a
210
+ sandbox that holds the resource, a credential, a command that does not exist yet — and send it to
211
+ the architect with `envoy_publish` to its role topic. The architect builds it in this tree
212
+ (infrastructure, tooling, or a skill), in an open pull request or a child issue, and resumes you
213
+ once it lands. A code path
214
+ whose first execution would be after the merge — a deploy
215
+ workflow's inline step, a post-merge helper, a production-only resource — is a check marked
216
+ `after_merge`, recorded once the merge reaches production, and no reason to leave a
217
+ `before_merge` check unrecorded; completing with a unit suite as the only evidence is the
218
+ failure this rule exists to stop.