@sjawhar/claude-envoy 1.20.3 → 1.21.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.omp-plugin/plugin.json +1 -1
- package/dist/envoy-channel.js +1 -1
- package/legion/agents/goal-red-team.md +30 -0
- package/legion/agents/plan-reviewer.md +13 -5
- package/legion/skills/legion-architect/SKILL.md +11 -10
- package/legion/skills/legion-architect/references/acceptance.md +47 -45
- package/legion/skills/legion-architect/references/design-gate.md +26 -29
- package/legion/skills/legion-architect/references/wake-routing.md +1 -1
- package/legion/skills/legion-worker/references/merge-gate.md +60 -65
- package/legion/skills/legion-worker/references/pr-body.md +32 -34
- package/package.json +1 -1
package/.omp-plugin/plugin.json
CHANGED
package/dist/envoy-channel.js
CHANGED
|
@@ -55262,7 +55262,7 @@ var import_nats2 = __toESM(require_mod4(), 1);
|
|
|
55262
55262
|
|
|
55263
55263
|
// package.json
|
|
55264
55264
|
var name = "@sjawhar/claude-envoy";
|
|
55265
|
-
var version2 = "1.
|
|
55265
|
+
var version2 = "1.21.0";
|
|
55266
55266
|
var legion = {
|
|
55267
55267
|
daemonApiVersion: 56
|
|
55268
55268
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: goal-red-team
|
|
3
|
+
description: |
|
|
4
|
+
Goal red team. It changes nothing. Use before you judge a change: reads the change against the
|
|
5
|
+
issue's goal and every requirement, and reports each met or unmet.
|
|
6
|
+
tools: Read, Bash
|
|
7
|
+
color: red
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You did not write this change. Your one job is whether it meets the issue's goal and every
|
|
11
|
+
requirement of its spec. The caller gives you the spec, the plan, the body and the diff.
|
|
12
|
+
|
|
13
|
+
Start from unmet: a requirement is met only when the head shows it. Read the code, not the body,
|
|
14
|
+
because a deferral reads like documentation and so is easiest to read past.
|
|
15
|
+
|
|
16
|
+
## What you report
|
|
17
|
+
|
|
18
|
+
One line per item: the goal first, then each requirement in the spec's order.
|
|
19
|
+
|
|
20
|
+
- **met** — the file and symbol that shows each part. A part delivered with a flaw in it is met,
|
|
21
|
+
and the flaw is a finding beside it.
|
|
22
|
+
- **unmet** — a part the spec names is missing: quote that part and what you read at the head.
|
|
23
|
+
|
|
24
|
+
You advise the caller, which decides.
|
|
25
|
+
|
|
26
|
+
## Constraints
|
|
27
|
+
|
|
28
|
+
- **You change nothing.** Run only commands that read. A write from a review agent is a change
|
|
29
|
+
nobody reviewed. Run jj with `--ignore-working-copy`.
|
|
30
|
+
- Your session carries the Dispatch and Envoy tools: read with them, write nothing.
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
name: plan-reviewer
|
|
3
3
|
description: |
|
|
4
4
|
Plan and spec reviewer. It changes nothing. Use after drafting a plan: checks that it can be
|
|
5
|
-
carried out as written, approves when in doubt
|
|
5
|
+
carried out as written, approves when in doubt except on the goal and the requirements, where
|
|
6
|
+
doubt is a rejection, and names at most three blocking issues, each
|
|
6
7
|
with its evidence. Use before every approval request of a spec: checks each factual claim in it
|
|
7
8
|
against the code, the docs or a read-only command it runs, and marks each claim verified, false
|
|
8
9
|
or unverified.
|
|
@@ -30,6 +31,12 @@ it out without getting stuck? You find blockers, not improvements.
|
|
|
30
31
|
`serves` of at least one `plan_task`, and each `check` has a task that makes it pass.
|
|
31
32
|
5. **A check that waits too long.** A check marked `after_merge` that could be run before the
|
|
32
33
|
merge is a blocking issue: it moves the proof past the gate that would have caught it.
|
|
34
|
+
6. **The goal and the requirements.** The plan delivers the issue's goal and every requirement of
|
|
35
|
+
its spec, each read as written, with each non-goal as a bound. One left out or narrowed is a
|
|
36
|
+
rejection that names it, and so is a plan whose own text says it leaves out work the goal
|
|
37
|
+
covers. Where a spec's own parts disagree on the scope of the goal, that is the owner's to
|
|
38
|
+
settle: reject, and say so. Never "approve when in doubt" here: doubt is a rejection that
|
|
39
|
+
says what is unclear.
|
|
33
40
|
|
|
34
41
|
You do not judge whether the approach is the best one, style, naming, edge cases the engineer can
|
|
35
42
|
settle during the work, or anything you would simply do differently.
|
|
@@ -38,8 +45,8 @@ settle during the work, or anything you would simply do differently.
|
|
|
38
45
|
|
|
39
46
|
Approve when in doubt. A plan that is mostly clear is good enough. Reject only for a blocker: a
|
|
40
47
|
reference that does not exist or does not hold what the plan says (read to confirm), a task with
|
|
41
|
-
nowhere to start, a contradiction, a requirement no task serves, a check no task makes pass,
|
|
42
|
-
check marked `after_merge` that could run before the merge.
|
|
48
|
+
nowhere to start, a contradiction, a requirement no task serves, a check no task makes pass, a
|
|
49
|
+
check marked `after_merge` that could run before the merge, or check 6.
|
|
43
50
|
|
|
44
51
|
A rejection names at most three blocking issues, the most severe first. Each gives:
|
|
45
52
|
|
|
@@ -52,8 +59,9 @@ raised again, and a second round is no place for requests that would not have bl
|
|
|
52
59
|
|
|
53
60
|
### Output
|
|
54
61
|
|
|
55
|
-
The first line is the verdict alone: `approved` or `rejected`. Then one
|
|
56
|
-
|
|
62
|
+
The first line is the verdict alone: `approved` or `rejected`. Then one line on the goal and the
|
|
63
|
+
requirements, outside the count below. Then one or two sentences on why.
|
|
64
|
+
On `rejected`, the numbered blocking issues, at most three. Nothing else.
|
|
57
65
|
|
|
58
66
|
## A spec
|
|
59
67
|
|
|
@@ -30,7 +30,7 @@ You own one issue tree from its first decision to the merge that closes it. The
|
|
|
30
30
|
- Work in a repository this tree already has a pull request in, which waits on a sibling's merge, is no child and is not parked in `backlog`: write it into the spec of the issue whose pull request carries it — the parent's, or the sibling's when the parent's pull request is in another repository — so one pull request lands it in order.
|
|
31
31
|
- A child that duplicates another issue and is not yet released is never released: fold it by the duplicate rule of `skill://dispatch-first`. The daemon records a child at its release and re-asserts a status only on an issue it has recorded, so that close stands. A released duplicate goes out with `park_child` instead.
|
|
32
32
|
- 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 work of this tree.
|
|
33
|
-
- The issue's primary document is the root spec: extend it in place, because a second "spec" artifact replaces the human's document. Mark each requirement of it as a `requirement` block, and write the issue's Verification document (`verification.md`) beside it: one `check` block per thing
|
|
33
|
+
- The issue's primary document is the root spec: extend it in place, because a second "spec" artifact replaces the human's document. Mark each requirement of it as a `requirement` block, and write the issue's Verification document (`verification.md`) beside it: one `check` block per thing to be proved, each with `serves` naming the requirements it serves, its `surface` (`browser`, `cli` or `api`), `run`, `when` (`before_merge`, `after_merge` or `default_branch`) and `negative_control`. The checks are the gate every later role reads: the implementer and the tester record a result against each, and the reviewer approves only once every `before_merge` check has a passing result current at the head. The decomposition's order and the plan's tasks go in the children and the planner's `plan` handoff, not the root spec.
|
|
34
34
|
- Before you write a design, state the problem to `task(agent="design-outsider")` and read its answer with `wait`. The brief holds the problem statement and the design principles, and no design of your own. The four questions are where the proposal is stupid, whether the thing in question should exist at all, what the smallest thing that gives the person what they asked for is, and what to delete. Record the answer in a comment on the issue, or in the issue's `plan.md` where one exists, before any action that states or favours a design, and give your reason where you do not follow it. Run the step once per design: at the first design of an issue, and again when a push-back or a review changes what the design is for. It is a challenge, never a gate.
|
|
35
35
|
- 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 names the design gate steps your `Legion addressing` line declares, the document each step records, and says that a sub-architect runs none.
|
|
36
36
|
- File every child of your decomposition before `dispatch request-approval`, and before `register_gate` where your line gates no step: the gate's opening starts your root's own first phase unless Dispatch shows an open child under it, so a child filed after it opens leaves the root working beside its children.
|
|
@@ -59,21 +59,22 @@ Your `sign_off` starts retro; never `envoy_publish` to the implementer to start
|
|
|
59
59
|
|
|
60
60
|
## 6. Acceptance and the merge
|
|
61
61
|
|
|
62
|
-
The reviewer's `phase-finished` with an `APPROVED` review puts the issue in `accepting`, where no worker runs. Against every check of
|
|
62
|
+
The reviewer's `phase-finished` with an `APPROVED` review puts the issue in `accepting`, where no worker runs. Against its goal, every check of its Verification document and every requirement its spec marks, read:
|
|
63
63
|
|
|
64
64
|
- the tester's handoff, `dispatch handoff-read --issue <issue> --phase test`;
|
|
65
|
-
- `dispatch results --issue <issue>`: each check, its latest result and whether
|
|
65
|
+
- `dispatch results --issue <issue>`: each check, its latest result and whether it is current at the approved head;
|
|
66
66
|
- the reviewer's approval of that head by SHA (`gh api --paginate repos/<o>/<r>/pulls/<n>/reviews`);
|
|
67
|
-
- each claim the reviewer's prose
|
|
67
|
+
- each claim the reviewer's prose makes, checked against the code at that head and command output, never against the finding it ruled on or its own verdict: no other agent reads it.
|
|
68
68
|
|
|
69
|
-
Accept only when every `before_merge` check of
|
|
69
|
+
A tree often brings its own shortfall written up; that is no permission: your job is the goal. Accept only when every `before_merge` check of this issue has a passing result current at the approved head, each requirement the spec states has a check, and no criterion left the tree; on a parent, that head is section 4's last round.
|
|
70
70
|
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
71
|
+
- Read each requirement as written: a narrower reading is unmet, and one unmet stops the sign-off, declared or not. A requirement is in the approved spec or it is not one: a person's later request becomes one once written there and approved. Where its parts disagree on scope, settling it is the owner's: ask, and hold the acceptance.
|
|
72
|
+
- Your role prompt carries the `goal-red-team` dispatch, before you decide the acceptance; on a root the requirements go to it at the version its gate approved, on a child, which has no gate, as they stand.
|
|
73
|
+
- A child's result against one of your checks proves nothing: its pull request never makes a root check's result current. A child carrying part of a root requirement proves it with a check of its own, clearing the root's coverage flag.
|
|
74
|
+
- An issue with no Verification document, or none holding a `before_merge` check, is a gap the tester and the reviewer name and neither refuses: its spec's delivered items are the requirements, met here or sent back. Checks you write close the `criteria` step where it is gated.
|
|
75
|
+
- A finding ask holds the acceptance until it resolves or the controller replies (`skill://legion-architect/references/acceptance.md`).
|
|
75
76
|
|
|
76
|
-
Post
|
|
77
|
+
Post it as a `dispatch comment` naming each check and its result, then `legion({ op: "sign_off", issue: "<KEY>" })`.
|
|
77
78
|
|
|
78
79
|
- `sign_off` works only in `accepting` (`SIGNOFF_OUTSIDE_ACCEPTING`), and the daemon refuses it while an issue beneath it is still in the workflow (`SIGNOFF_CHILD_IN_WORKFLOW`, naming each one), so a parent is accepted after its children, on the head of its last round (section 4).
|
|
79
80
|
- When a check has no current passing result, or its result contradicts what you read: `request_backward_move` with `issue`, `to` (`implementing` or `testing`) and a `reason` naming the check by its block id. It counts a review round.
|
|
@@ -19,8 +19,9 @@ missing instruction.
|
|
|
19
19
|
|
|
20
20
|
## Accepting
|
|
21
21
|
|
|
22
|
-
Sign off an issue with no children once its evidence holds
|
|
23
|
-
|
|
22
|
+
Sign off an issue with no children once its evidence holds for its goal and every requirement of
|
|
23
|
+
its spec, none unmet; a parent only after its last round (below), because
|
|
24
|
+
before it the approved head does not carry its children's merges.
|
|
24
25
|
|
|
25
26
|
```text
|
|
26
27
|
dispatch comment --issue LEGION-40 --body-file - <<'EOF'
|
|
@@ -31,9 +32,9 @@ legion({ op: "sign_off", issue: "LEGION-40" })
|
|
|
31
32
|
|
|
32
33
|
- The issue's Dispatch status stays `needs_review` in `accepting`; `sign_off` moves it to `retro`.
|
|
33
34
|
- A `catch-up` whose `reason` names an issue as waiting for your acceptance is the wake for it: it
|
|
34
|
-
is in `accepting`, and the `phase-finished`
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
is in `accepting`, and the `phase-finished` that moved it there may never have reached you (a
|
|
36
|
+
failed architect's notice is dropped, so a retried one learns of the wait from its catch-up
|
|
37
|
+
alone). Accept it as this section says, a parent only after its last round (below).
|
|
37
38
|
- The daemon refuses `sign_off` while an issue beneath the one you accept is still in the workflow
|
|
38
39
|
(`SIGNOFF_CHILD_IN_WORKFLOW`, naming each one): take each one to done, or out of the workflow
|
|
39
40
|
with `park_child`, and sign off again. A parent: sign off only after its last round (below). The
|
|
@@ -49,27 +50,28 @@ legion({ op: "sign_off", issue: "LEGION-40" })
|
|
|
49
50
|
- A finding ask on the issue holds the acceptance: one a worker sent you, or one `dispatch read`
|
|
50
51
|
lists under `Open asks:` whose question opens `Finding from ` or `Clear defect from `
|
|
51
52
|
(`skill://legion-worker/references/findings.md`, "When no controller takes it"). Follow each
|
|
52
|
-
(`dispatch follow --ask <id> --action follow`) and, once
|
|
53
|
-
|
|
54
|
-
`Filed dispatch://`, `Handed dispatch://` or `Not filed:` reply, because a closed issue hides
|
|
55
|
-
asks from the controller.
|
|
53
|
+
(`dispatch follow --ask <id> --action follow`) and, once answered, publish its reference to the
|
|
54
|
+
controller topic. Accept only once each is resolved or carries the controller's
|
|
55
|
+
`Filed dispatch://`, `Handed dispatch://` or `Not filed:` reply, because a closed issue hides
|
|
56
|
+
its asks from the controller.
|
|
56
57
|
|
|
57
58
|
## The last round
|
|
58
59
|
|
|
59
|
-
A parent's own pull request proves each of its checks, so sign off a parent
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
a check in another repository is older than the close of a child it
|
|
69
|
-
the issue in `accepting` until each
|
|
70
|
-
|
|
71
|
-
it.
|
|
72
|
-
|
|
60
|
+
A parent's own pull request proves each of its checks, so sign off a parent with children only
|
|
61
|
+
on an approved head carrying the merges of every child those checks need. Each needs a current
|
|
62
|
+
passing result at that head, or, for one in another repository, at a commit that repository's
|
|
63
|
+
default branch carries. A child records no result that proves a parent's check: a child's pull
|
|
64
|
+
request never makes a parent check's result current, and a child carrying part of a parent's
|
|
65
|
+
requirement proves it with a check on its own Verification document whose `serves` names that
|
|
66
|
+
requirement. Nothing in the tree builds on the parent's own merge, which comes last: a child
|
|
67
|
+
that waits for it waits forever, so work another child builds on is a child of its own, in a
|
|
68
|
+
repository of its own or with a deploy of its own. While the approved head does not carry those
|
|
69
|
+
merges, or the result of a check in another repository is older than the close of a child it
|
|
70
|
+
needs, leave the issue in `accepting` until each has closed (`child-closed`) or been parked for
|
|
71
|
+
good (`child-status`). Move a parked child's criterion to the root's own pull request or a
|
|
72
|
+
released, open child first; never downgrade it. A root's requirement stays the root's, pending
|
|
73
|
+
until this round, where its head must meet it.
|
|
74
|
+
Then, in one turn:
|
|
73
75
|
|
|
74
76
|
1. `envoy_publish` to the tester's role topic: "The next round of <KEY> is its last round: a full
|
|
75
77
|
test round of every check of the issue, not the forward-merge re-check." The backward move's
|
|
@@ -80,15 +82,15 @@ in one turn:
|
|
|
80
82
|
counts a review round.
|
|
81
83
|
|
|
82
84
|
While the parent waits in `accepting`, a conflict on its head or a child's merge needs no move of
|
|
83
|
-
its own: the last round's forward merge resolves them all, so spend no backward move per child
|
|
84
|
-
|
|
85
|
+
its own: the last round's forward merge resolves them all, so spend no backward move per child;
|
|
86
|
+
each counts toward `review_round_cap`.
|
|
85
87
|
|
|
86
|
-
A criterion proven on a deployed system is proven
|
|
87
|
-
|
|
88
|
+
A criterion proven on a deployed system is proven after that child's deploy, as the repository's
|
|
89
|
+
deploy skill says.
|
|
88
90
|
|
|
89
91
|
If the pull request merged before its last round, it can carry no new head, so move nothing back.
|
|
90
|
-
Once
|
|
91
|
-
|
|
92
|
+
Once they have closed, have a fresh `task` subagent run each check on the default branch,
|
|
93
|
+
record each result, post them in the acceptance comment, then `sign_off`.
|
|
92
94
|
|
|
93
95
|
## The order after your acceptance
|
|
94
96
|
|
|
@@ -115,13 +117,16 @@ The daemon keeps this order from its fixed table; you start none of its steps:
|
|
|
115
117
|
5. The merge lands under the repository's rules and closes the issue; a root's close waits until
|
|
116
118
|
the rest of its tree has left the workflow.
|
|
117
119
|
|
|
118
|
-
A
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
A person's request after your sign-off is a requirement of this issue, filed nowhere else: in
|
|
121
|
+
`retro` or `merging` the role holding the phase makes the `request_backward_move`; in
|
|
122
|
+
`awaiting_merge` the implementer pushes, which withdraws the READY.
|
|
123
|
+
A refused or failed READY arrives while the merger holds `merging`, so the merger makes the move
|
|
124
|
+
and you tell it which; from `accepting` you send an issue back only to `implementing` or
|
|
125
|
+
`testing`.
|
|
121
126
|
|
|
122
|
-
-
|
|
123
|
-
`skill://legion-architect/references/wake-routing.md` says
|
|
124
|
-
back with `request_backward_move`, naming what failed; never bypass.
|
|
127
|
+
- A failed verification the merger reports: handle it as the `pr-blocked` row of
|
|
128
|
+
`skill://legion-architect/references/wake-routing.md` says, telling the merger to move the
|
|
129
|
+
issue back with `request_backward_move`, naming what failed; never bypass.
|
|
125
130
|
- `READY_UNREVIEWED_CHANGE`, or a merger task with no approved head (`READY_NOT_APPROVED`): the
|
|
126
131
|
merger moves it back to `reviewing`, the reason naming the code and what it found, so the
|
|
127
132
|
reviewer runs a new round.
|
|
@@ -132,8 +137,7 @@ What returns the tree to review is a changed diff: a commit above the approved h
|
|
|
132
137
|
anything outside `docs/solutions/`, other than a change whose every path is under `.legion/`, or
|
|
133
138
|
a conflict-resolution merge whose fingerprint (the unchanged-diff check,
|
|
134
139
|
`skill://legion-worker/references/conflicts-and-rewrites.md`) differs from the approved head's.
|
|
135
|
-
A merge
|
|
136
|
-
not, and neither does a commit that changes only `docs/solutions/`.
|
|
140
|
+
A conflict merge whose fingerprint is unchanged does not.
|
|
137
141
|
|
|
138
142
|
Make a conflict-resolution merge only when GitHub reports `CONFLICTING`
|
|
139
143
|
(`gh pr view <n> --json mergeable,mergeStateStatus`). Outside `awaiting_merge` the daemon records
|
|
@@ -147,14 +151,12 @@ a conflict and moves nothing, so the moment you see it:
|
|
|
147
151
|
`the head conflicts with <base>`.
|
|
148
152
|
|
|
149
153
|
The daemon then runs the phases from `implementing`: the implementer merges the bookmark forward
|
|
150
|
-
with the destination
|
|
151
|
-
`skill://legion-worker/references/conflicts-and-rewrites.md
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
new head by SHA, or continues its round if it had not approved; the daemon carries the issue
|
|
157
|
-
through your acceptance and retro to the merger's new READY.
|
|
154
|
+
with the destination and pushes it (the procedure in
|
|
155
|
+
`skill://legion-worker/references/conflicts-and-rewrites.md`), posting the before and after
|
|
156
|
+
fingerprints; the tester re-runs the bare gates only and the class search of every earlier
|
|
157
|
+
round's findings at the new head; the reviewer approves the new head by SHA, or continues its
|
|
158
|
+
round if it had not approved; the daemon carries the issue through your acceptance and retro to
|
|
159
|
+
the merger's new READY.
|
|
158
160
|
|
|
159
161
|
## A review thread GitHub will not resolve
|
|
160
162
|
|
|
@@ -189,12 +189,11 @@ reason, and answer it in the spec if the latest version does not already.
|
|
|
189
189
|
## After approval
|
|
190
190
|
|
|
191
191
|
Each step's approval is pinned to the version of the document that step records: a new version of
|
|
192
|
-
that document closes that step again,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
answer to a decision block
|
|
192
|
+
that document closes that step again, with no wake to say so; you know from your own edit, or
|
|
193
|
+
from the `artifact.version` event on your issue. One step closing holds the tree's work whatever
|
|
194
|
+
the other steps stand at. The exceptions are the version a human's own answer to a decision block
|
|
196
195
|
writes when that answer is the whole change since the version they approved, and a version whose
|
|
197
|
-
text is exactly
|
|
196
|
+
text is exactly that of the version they approved, with no decision block in it decided
|
|
198
197
|
since, such as an accidental edit undone exactly: for either, Dispatch records an `approved`
|
|
199
198
|
review in their name at the new version and emits `artifact.approved`, and the daemon reopens the
|
|
200
199
|
gate and sends `design-approved`. Undo an accidental edit of an approved root spec exactly. When
|
|
@@ -202,45 +201,43 @@ the spec then reads Approved at the new version, request nothing; when it does n
|
|
|
202
201
|
it was decided since), request approval again with steps 3 to 5.
|
|
203
202
|
|
|
204
203
|
So edit an approved root spec only when its Summary, a requirement it marks, a check of its
|
|
205
|
-
Verification document, the tree's scope
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
at the end of the section it changes, and add nothing else to the spec. If you edit the block before
|
|
204
|
+
Verification document, the tree's scope or a settled decision changes. Such a change is a point
|
|
205
|
+
the human has not agreed to: put the problem behind it to them as its own decision block, with
|
|
206
|
+
its evidence, at the end of the section it changes, and add nothing else. If you edit the block before
|
|
209
207
|
the human answers, the gate closes like any new version, but their answer still carries the approval
|
|
210
208
|
to the version it writes. Once they have answered:
|
|
211
209
|
|
|
212
210
|
- When the answer is the whole change, request nothing: the document's chip reads Approved at the
|
|
213
|
-
new version
|
|
214
|
-
|
|
215
|
-
- When the answer changes the Summary, a requirement, a check or the tree's scope, rewrite that
|
|
216
|
-
repeat steps 3 to 5 on the new version, with a one-sentence `--summary` naming what
|
|
217
|
-
the earlier approval, then the reviews' sentence (the card shows
|
|
211
|
+
new version and the `design-approved` the daemon sent opens nothing new. Carry on; release no
|
|
212
|
+
child because of it.
|
|
213
|
+
- When the answer changes the Summary, a requirement, a check or the tree's scope, rewrite that
|
|
214
|
+
text and repeat steps 3 to 5 on the new version, with a one-sentence `--summary` naming what
|
|
215
|
+
changed since the earlier approval, then the reviews' sentence (the card shows `Approved at
|
|
218
216
|
version N on <date> by <who>.`, and its `Show diff` control carries the detail). The rewrite
|
|
219
|
-
closes the gate until they approve
|
|
220
|
-
work the daemon started at the answer
|
|
221
|
-
|
|
222
|
-
refused until a human approves the latest version.
|
|
217
|
+
closes the gate until they approve. Release no further child until the `design-approved` after
|
|
218
|
+
it; work already in flight, including what the daemon started at the answer, continues. Every
|
|
219
|
+
merger's `READY` in the tree is refused until a human approves the latest version.
|
|
223
220
|
|
|
224
221
|
A settled decision is the human's. A plan that would overturn one goes back to the planner with the
|
|
225
222
|
decision kept, unless the planner brings evidence the human did not weigh that would change it
|
|
226
223
|
(such as a measurement showing the settled choice cannot pass a check); then a decision
|
|
227
224
|
block names the decision and that evidence. A plan never overturns a settled decision on its own.
|
|
225
|
+
A person's request after the approval becomes a requirement only when you write it into the spec
|
|
226
|
+
and they approve that version; it is never another issue's, and no comment or answer of theirs
|
|
227
|
+
takes a requirement out.
|
|
228
228
|
|
|
229
229
|
A design change that leaves the Summary, the requirements, the checks, the scope and the settled
|
|
230
|
-
decisions intact (a
|
|
231
|
-
|
|
232
|
-
issue's `plan.md` document and the planner's `plan` handoff on the issue), never into the approved spec, even
|
|
230
|
+
decisions intact (a planner's measurement finding a better way to the same outcome) goes in the
|
|
231
|
+
plan (the issue's `plan.md` and the planner's `plan` handoff), never into the approved spec, even
|
|
233
232
|
where the spec's text describes the older design; the reviewer reads the plan beside the spec.
|
|
234
233
|
|
|
235
|
-
When a planner's `phase-finished` names a departure
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
the plan is the record and the tree carries on; otherwise change the root spec and request
|
|
239
|
-
approval again.
|
|
234
|
+
When a planner's `phase-finished` names a departure, compare it with the approved spec: with the
|
|
235
|
+
Summary, the requirements, the checks, the scope and every settled decision unchanged, the plan
|
|
236
|
+
is the record and the tree carries on; otherwise change the root spec and request approval again.
|
|
240
237
|
|
|
241
|
-
Later children and re-scoping open children toward the same requirements need no spec edit and no
|
|
242
|
-
approval. A child issue's spec is never gated, and the child's own
|
|
243
|
-
|
|
238
|
+
Later children and re-scoping open children toward the same requirements need no spec edit and no
|
|
239
|
+
new approval. A child issue's spec is never gated, and its architect writes the child's own
|
|
240
|
+
Verification document.
|
|
244
241
|
|
|
245
242
|
## A decision block for a read no pod can make
|
|
246
243
|
|
|
@@ -27,7 +27,7 @@ and 7 (a conflict, the hand-over, the close) is in
|
|
|
27
27
|
| `design-approved` | Its `version` is the approved one, and it names no step: under more than one gated step, read `gatedSteps` in your own record (the `legion` tool's `read_record`) to see which step that version opened and whether another still holds the tree. A human approved the document of one gated step at its current version; that step is open. Proceed to section 2 once every gated step is `approved` — 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 child 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. |
|
|
28
28
|
| `design-changes-requested` | Its `version` and `reason`, and no step: under more than one gated step, read `gatedSteps` in your own record (the `legion` tool's `read_record`) and take the step whose `status` is `changes_requested`. A human asked for changes to that step's document at `version`, for `reason`. Revise that document as the reason asks and request approval again as "The armed gate" in `skill://legion-architect/references/design-gate.md` says; end your turn; that step 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. |
|
|
29
29
|
| `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 finishing phase's handoff on the Dispatch issue (`dispatch handoff-read --issue <issue> --phase <word>`); 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, the requirements, the checks, the scope and the 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` (a parent only after its last round, "The last round" in `skill://legion-architect/references/acceptance.md`) or send it back with `request_backward_move`. A `tester` notice with `verdict: "fail"` — its handoff carries `implementerProof.verdict: "rejected"`, or a failure naming a check with no current passing result — has gone back to the **implementer** by the daemon's table; never record that check's result 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: build the surface in this tree: a child issue (infrastructure, tooling, or a skill) after the red-team check in `skill://legion-architect/references/decomposition.md`, or, when the red team folds it, tell the waiting worker to move the issue back to `implementing` with `request_backward_move`, naming the surface. When it is a child, tell the waiting worker to continue with `envoy_publish` to its role topic once that child's `child-closed` arrives. That report is never a reason to advance the phase. |
|
|
30
|
-
| `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: no handoff is a commit, so every such push counts except a push by the review App (a planner's, tester's, reviewer's or architect's), and the head pushed onto a red the tester's red tests earned (a planned red) does not count either. 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 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. 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 checks
|
|
30
|
+
| `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: no handoff is a commit, so every such push counts except a push by the review App (a planner's, tester's, reviewer's or architect's), and the head pushed onto a red the tester's red tests earned (a planned red) does not count either. 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 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. 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 checks the next round answers, dropping no requirement; 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 it does not touch. **Split**: part of the work cannot settle in this pull request. It is a child only when it needs a repository or a deploy order of its own (`skill://legion-architect`, section 1), and then it goes through the red-team check in `skill://legion-architect/references/decomposition.md` and is filed as a child of this issue's parent, never of this one, since this issue closes at its own merge. A requirement moves only to that released child. Work in a repository this tree already has a pull request in is no child and is not parked in `backlog`: write it into the spec of the issue whose pull request carries it, the parent's, or a sibling's when the parent's pull request is in another repository. On the root, open a `dispatch ask` for the part that cannot settle here (`skill://legion-worker/references/findings.md`): it stays this issue's requirement, and this pull request carries it, until the person who answers that ask records that the issue will not deliver 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 requires or what a check proves 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. |
|
|
31
31
|
| `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`, its workers kept and live and no admission slot held, 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. |
|
|
32
32
|
| `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. |
|
|
33
33
|
| `pull-request-missing` | Its `reason` names the issue, the repository, the branch and the handoff commit: the issue's implementer completed at that commit and GitHub lists no open pull request on the branch, so the issue stays in `implementing`. Tell the implementer (`envoy_publish` to its role topic) to open the pull request from that branch; the daemon records it and moves the issue to `testing` once it is open. When the work should not go on, decide as the `pr-closed-unmerged` row says. It comes once per handoff commit. |
|
|
@@ -145,22 +145,19 @@ reviewing until you finish.
|
|
|
145
145
|
`legion` tool's `sign_off`, which moves the issue to retro, or sends it back to `implementing`
|
|
146
146
|
or `testing` with `request_backward_move` and a reason, which reaches the started worker's task
|
|
147
147
|
as its `Reason:` line and counts a review round. The acceptance comment names each check with
|
|
148
|
-
its result. An issue with no Verification document, or
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
The acceptance asks for no `after_merge` result: that one is recorded
|
|
162
|
-
after the close, where the project opens a check (*The production check after the close*,
|
|
163
|
-
below).
|
|
148
|
+
its result. An issue with no Verification document, or none holding a `before_merge` check,
|
|
149
|
+
is a gap the tester and the reviewer named and neither refused, so that comment is its only
|
|
150
|
+
gate: it names the gap and decides how each delivered item is proven at this head, never
|
|
151
|
+
whether one stays unmet; checks it writes close the root's `criteria` step where the
|
|
152
|
+
deployment gates it, since that step records the root's Verification document, and a child's
|
|
153
|
+
is gated by nothing. It also reads the reviewer's prose commits here with the rest, no new
|
|
154
|
+
round, and does
|
|
155
|
+
not accept while the issue holds a finding ask no controller took (`findings.md`, "When no
|
|
156
|
+
controller takes it"). Approval is gated by the `before_merge` checks of the issue's own
|
|
157
|
+
Verification document at its head, so a child's result against a root's check proves nothing:
|
|
158
|
+
a root's checks are proven at its own head, in its last round. No `after_merge` result is
|
|
159
|
+
asked here: it is recorded after the close, where the project opens a check (*The production
|
|
160
|
+
check after the close*, below).
|
|
164
161
|
CI red at the head in `accepting` returns the issue to `implementing` as it does in review. A
|
|
165
162
|
head the review App pushed is the exception: the daemon marks it a planned red and acts on it
|
|
166
163
|
nowhere, and GitHub holds the merge under the base branch's own rules.
|
|
@@ -289,53 +286,53 @@ reviewing until you finish.
|
|
|
289
286
|
after the close.** `projects.<KEY>.production_check` in the project's `legion.yaml` takes `off`
|
|
290
287
|
or `tester`, and a project that names no key gets `tester`, so by default the tester works the
|
|
291
288
|
check; the loader refuses every other value, naming the key and the value it read. Where the
|
|
292
|
-
setting names the tester, the merge makes the daemon write `done` and
|
|
293
|
-
|
|
289
|
+
setting names the tester, the merge makes the daemon write `done` and hand the check task to
|
|
290
|
+
the tester's live session. Where it is `off` nothing is opened at all — no record, no
|
|
294
291
|
bound and no look — and the merged close is like any other done: every claim of the issue is
|
|
295
292
|
retired and its pod released with the disk it ran on. A merged root still lingers its tree with
|
|
296
|
-
every claim suspended, as before. On a root whose tree still runs the
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
`Production check of <KEY>: <title>.`,
|
|
300
|
-
commit, the look's number,
|
|
301
|
-
|
|
302
|
-
from its last phase task by that first line.
|
|
293
|
+
every claim suspended, as before. On a root whose tree still runs, the merge is recorded and
|
|
294
|
+
the root waits in `awaiting_merge` until the last other issue of its tree is done or parked,
|
|
295
|
+
the check opening with that close. Its first line, which tells it from a phase task in a
|
|
296
|
+
resumed session, is `Production check of <KEY>: <title>.`, naming the repository, the pull
|
|
297
|
+
request, the merge commit, the look's number, its wake (`the merge`, for the first) and whether
|
|
298
|
+
it is the last.
|
|
303
299
|
- **The check's record holds the role that works it, written when the check opened.** Changing the
|
|
304
300
|
setting moves no check already open: a check keeps the role it opened with, and a check open
|
|
305
301
|
before this release carries the implementer. Only that role may report on it, so a report from
|
|
306
302
|
any other role is refused (`CHECK_ROLE_MISMATCH`). The check carries no phase and no handoff: a
|
|
307
|
-
look ends with `handoff_complete` carrying a `verdict` and a `summary
|
|
308
|
-
refuses a report
|
|
309
|
-
(`CHECK_LOOK_NOT_OPEN`)
|
|
303
|
+
look ends with `handoff_complete` carrying a `verdict` and a `summary` and no commit, and the
|
|
304
|
+
daemon refuses a report with no open check (`CHECK_NOT_OPEN`), on an ended look
|
|
305
|
+
(`CHECK_LOOK_NOT_OPEN`) or with no verdict
|
|
310
306
|
(`CHECK_VERDICT_REQUIRED`).
|
|
311
307
|
One refusal is about the turn rather than the report: a completion sent from a turn that is not
|
|
312
308
|
a look's own task is refused `CHECK_LOOK_NOT_SERVED` and records nothing, so report again in the
|
|
313
309
|
turn of the look's task.
|
|
314
310
|
- **Each look does three things.** Do what the deployment instructions say to reach the deploy:
|
|
315
311
|
when they name an agent or role for it, `envoy_publish` the merge commit to that role's topic
|
|
316
|
-
with `expects_reply: false`, and await no reply. Read whether production carries the merge
|
|
312
|
+
with `expects_reply: false`, and await no reply. Read whether production carries the merge, and
|
|
313
|
+
with it every requirement only the deploy can show, each as the requirement names it, since
|
|
314
|
+
observing something else is never that requirement observed. Then
|
|
317
315
|
report one of three outcomes:
|
|
318
|
-
- `pass`, once you drove the changed path in production through the
|
|
316
|
+
- `pass`, once you drove the changed path and those requirements in production through the
|
|
317
|
+
user's own access path and
|
|
319
318
|
recorded the result: `dispatch result` against the issue's `after_merge` check, at the merge
|
|
320
|
-
commit, its `observed` ending `woken by <event>`,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
pass is not this, since a
|
|
325
|
-
staging gate does not run every resource production does.
|
|
319
|
+
commit, its `observed` ending `woken by <event>`, the printed line in the PR body's `Checks`
|
|
320
|
+
block and one pull-request comment with the Legion footer. A closed issue takes a result for
|
|
321
|
+
an `after_merge` or `default_branch` check, a comment and a message, and refuses every other
|
|
322
|
+
write. A staging pass is not this: staging does not run every resource production does.
|
|
326
323
|
- `pending`, when production does not carry the merge yet (a shared profile still holding the
|
|
327
|
-
previous release, a daemon still running the previous commit, a deploy nobody has run)
|
|
328
|
-
summary names what is missing and what you
|
|
329
|
-
(below), nothing is recorded, and the
|
|
324
|
+
previous release, a daemon still running the previous commit, a deploy nobody has run), or a
|
|
325
|
+
requirement's observation has not happened: the summary names what is missing and what you
|
|
326
|
+
will look for next, `wake_at` names your next look (below), nothing is recorded, and the
|
|
327
|
+
check's line in the body stays at
|
|
330
328
|
`- Check <block id> (after_merge): not yet run`.
|
|
331
|
-
- `fail`, for a
|
|
332
|
-
issue, and
|
|
333
|
-
`skill://legion-worker/references/findings.md` gives it
|
|
334
|
-
controller topic, with its evidence comment on the controller's report issue
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
result's `observed` and in the summary.
|
|
329
|
+
- `fail`, for a requirement observed as not met, one still unobserved at the last look, or a
|
|
330
|
+
defect: record the failing result with `dispatch result --verdict fail`, file no issue, and
|
|
331
|
+
take the path `skill://legion-worker/references/findings.md` gives it — a clear fix to the
|
|
332
|
+
controller topic, with its evidence comment on the controller's report issue; one needing a
|
|
333
|
+
decision as a `dispatch ask` there, whose reference you publish to that topic. Either names
|
|
334
|
+
this issue, the pull request, the merge commit, what you drove and what failed, and the
|
|
335
|
+
result's `observed` and the summary name it (`dispatch://<REPORT KEY>/ask/<id>`).
|
|
339
336
|
- **Numbers the daemon holds are read with the `legion` tool.** Where the verdict rests on what a
|
|
340
337
|
deployment's idle release has done, `read_release_records` answers a window of the daemon's own
|
|
341
338
|
records of its releases, resumes and holds: its one argument `since` is the RFC 3339 instant
|
|
@@ -357,29 +354,27 @@ reviewing until you finish.
|
|
|
357
354
|
- **Nothing waits in the session for a deploy.** A `pending` ends the look: the daemon stops the
|
|
358
355
|
checking role's process, keeps its session and releases the issue's pod, whose Sandbox goes with
|
|
359
356
|
its disk, and at the time you named a new pod comes back and your session resumes with the next
|
|
360
|
-
look's task. So end the turn with the report: never poll
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
look still ends `pending`.
|
|
357
|
+
look's task. So end the turn with the report: never poll, never wait on a reply, never ask for
|
|
358
|
+
approval to deploy. Open a `dispatch ask` only where the instructions name nobody: the
|
|
359
|
+
production gap and why it matters, then the required install or restart step, its risk, and
|
|
360
|
+
outcome-named options; the look still ends `pending`.
|
|
365
361
|
- **The bounds.** A look is bounded at 2 hours, and a look nobody reported — its 2 hours, an
|
|
366
362
|
operator's hold, or a claim that failed to start — starts the next look two hours later; on the
|
|
367
|
-
last look it closes the check as not run. The
|
|
368
|
-
`production_check_hours` (336, 14 days, by default) from the close
|
|
369
|
-
|
|
363
|
+
last look it closes the check as not run. The check is bounded by the project's
|
|
364
|
+
`production_check_hours` (336, 14 days, by default) from the close; the look that bound starts
|
|
365
|
+
is the last, so told in its task
|
|
370
366
|
(`the bound: production did not carry the merge within <N days>`). A `pass` or `fail` there
|
|
371
|
-
closes the check as any look's would
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
bound.
|
|
367
|
+
closes the check as any look's would, and a requirement still unobserved there is that `fail`;
|
|
368
|
+
only production not carrying the merge ends it `pending`, which carries no `wake_at` and
|
|
369
|
+
closes the check as not run, written first on the pull request — its check line and a comment
|
|
370
|
+
— because production did not carry the merge within the bound.
|
|
375
371
|
- **The record lives on the pull request and in the result.** Dispatch takes a comment, a message
|
|
376
372
|
and a result for an `after_merge` or `default_branch` check on a closed issue, and refuses an
|
|
377
|
-
ask there (`ISSUE_CLOSED`), so the deployment instructions' "on the pull request
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
and
|
|
381
|
-
|
|
382
|
-
nothing after it. `pass` or
|
|
373
|
+
ask there (`ISSUE_CLOSED`), so the deployment instructions' "on the pull request and the issue"
|
|
374
|
+
is the pull request and that result, and a defect reaches Dispatch by the `fail` verdict's two
|
|
375
|
+
paths alone — the message to the controller, which gives it to the tree that owns that code,
|
|
376
|
+
and the ask on the controller's report issue. The architect accepted before the
|
|
377
|
+
merge and is asked nothing after. `pass` or
|
|
383
378
|
`fail` closes the check: your claim is retired and the issue's Sandbox goes with its pod and
|
|
384
379
|
disk, for a root as for a child. Neither ending retires or suspends anything of an issue back in
|
|
385
380
|
the workflow (a root reopened inside its linger): its claim and pod are the new run's.
|
|
@@ -98,10 +98,10 @@ command prints the pull request body's line for it, and that line goes into the
|
|
|
98
98
|
The surface is **production-like** — the repository's real-process test harness and fixtures, a
|
|
99
99
|
sandbox repository, a real browser, a devN stack, staging, or a local stack with real migrations,
|
|
100
100
|
one that has the resource the change touches — and `--run` or `--observed` carries a **link** to
|
|
101
|
-
that run, screenshot
|
|
102
|
-
unit suite is not it. A unit or integration test is a regression lock, never
|
|
103
|
-
|
|
104
|
-
|
|
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 a check's result.
|
|
103
|
+
The agent that develops the change records its results this way before the merge, and whatever
|
|
104
|
+
blocks a check is fixed, not skipped (*When no surface reaches the changed path*, below).
|
|
105
105
|
|
|
106
106
|
**Record a result after the commit is pushed.** Dispatch asks GitHub whether the repository of
|
|
107
107
|
the check's issue holds the commit, and refuses a result at one it does not hold with `400
|
|
@@ -121,31 +121,30 @@ issue, or the final head of a merged one, and the check's words have not changed
|
|
|
121
121
|
`after_merge` or `default_branch` result is current at a commit the default branch carries. A push
|
|
122
122
|
makes every result at the old head older, with no Dispatch write of anyone's, so each check is
|
|
123
123
|
recorded again at the new head. `dispatch results --issue <issue>` prints each check with its
|
|
124
|
-
latest result and whether
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
**An issue is proved by its own checks.**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
gap and decides there, which is the only gate on such an issue.
|
|
124
|
+
latest result and whether it is current; `dispatch read --issue <issue>` names each requirement
|
|
125
|
+
of the spec no check serves.
|
|
126
|
+
|
|
127
|
+
**An issue is proved by its own checks.** Approval is gated by the `before_merge` checks of its
|
|
128
|
+
own Verification document, read at its own head, so a child's pull request never makes a root
|
|
129
|
+
check's result current and a child never records the result that proves a root's check. A child
|
|
130
|
+
carrying part of a root's requirement proves it with a check on its own Verification document
|
|
131
|
+
whose `serves` names that requirement. A root's own checks are proven at its own head, or on the
|
|
132
|
+
default branch for an `after_merge` check, in its last round.
|
|
133
|
+
|
|
134
|
+
**An issue with no `before_merge` check is a named gap.** One with no Verification document, or
|
|
135
|
+
with none holding a `before_merge` check, has no evidence of its own. The tester names the gap
|
|
136
|
+
in its handoff and the reviewer in its review, and neither sends the issue back for it; both
|
|
137
|
+
tell the architect, who writes the checks, and the architect's acceptance comment names the gap
|
|
138
|
+
and decides there, the only gate on such an issue.
|
|
140
139
|
|
|
141
140
|
## The rules every phase's evidence follows
|
|
142
141
|
|
|
143
142
|
- **The implementer records a result for every `before_merge` check before its phase completes,
|
|
144
143
|
and writes the `Checks` lines when the pull request opens.**
|
|
145
144
|
A check with no surface yet is the report of *When no surface reaches the changed path* below,
|
|
146
|
-
never a check left unrecorded. The results are on the Dispatch issue,
|
|
145
|
+
never a check left unrecorded. The results are on the Dispatch issue, the lines in the
|
|
147
146
|
PR body, because the reviewer and the merger verify facts on GitHub and never from a handoff.
|
|
148
|
-
The `implement` handoff carries
|
|
147
|
+
The `implement` handoff carries none: Dispatch holds them, and the tester reads them with
|
|
149
148
|
`dispatch results`.
|
|
150
149
|
- **The tester judges the implementer's results and records its own.** It re-runs the
|
|
151
150
|
implementer's command or drives the same surface independently, and records the verdict in
|
|
@@ -201,11 +200,12 @@ gap and decides there, which is the only gate on such an issue.
|
|
|
201
200
|
Record both in the `Thermo` line.
|
|
202
201
|
- **No deferrals** is the body's rule (*PR body, review, and the merge gate* in
|
|
203
202
|
`skill://legion-worker`): a wording nit, and any clear fix in a file this pull request touches,
|
|
204
|
-
is made in the running round
|
|
205
|
-
change
|
|
206
|
-
|
|
207
|
-
`none
|
|
208
|
-
A base frozen for others to stack on is
|
|
203
|
+
is made in the running round: a later round costs a CI pass and a re-read of the whole
|
|
204
|
+
change. A requirement on the `Not proven / risk:` line is unmet, not declared away, unless only
|
|
205
|
+
the deploy can show it and the plan names its observation;
|
|
206
|
+
the `Fast-follow:` line never carries one, and reads `none` or names only cleanup in files
|
|
207
|
+
this pull request does not touch. A base frozen for others to stack on is
|
|
208
|
+
never rewritten (*Rewriting pushed commits* in
|
|
209
209
|
`skill://legion-worker/references/conflicts-and-rewrites.md`); the `Chain` line records it.
|
|
210
210
|
- **GitHub refuses a pull request body over 65,536 characters.** Each verification round links its
|
|
211
211
|
evidence (the run, the comment) rather than inlining it once the body passes about 48,000
|
|
@@ -218,10 +218,8 @@ Say which surface is missing and what it would have to do — a rig that can spa
|
|
|
218
218
|
sandbox that holds the resource, a credential, a command that does not exist yet — and send it to
|
|
219
219
|
the architect with `envoy_publish` to its role topic. The architect builds it in this tree
|
|
220
220
|
(infrastructure, tooling, or a skill), in an open pull request or a child issue, and resumes you
|
|
221
|
-
once it lands. A code path
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
`
|
|
225
|
-
|
|
226
|
-
`before_merge` check unrecorded; completing with a unit suite as the only evidence is the
|
|
227
|
-
failure this rule exists to stop.
|
|
221
|
+
once it lands. A code path whose first execution would be after the merge — a deploy workflow's
|
|
222
|
+
inline step, a post-merge helper, a production-only resource — is a check marked `after_merge`,
|
|
223
|
+
recorded once the merge reaches production by the role the project's `production_check` names,
|
|
224
|
+
on the look its own `wake_at` brought back, and no reason to leave a `before_merge` check
|
|
225
|
+
unrecorded; completing with a unit suite as the only evidence is the failure this rule stops.
|