@sjawhar/pi-legion 11.2.0 → 11.4.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/dist/legion.js +1364 -10355
- package/dist/skills/legion-architect/SKILL.md +2 -0
- package/dist/skills/legion-architect/references/decomposition.md +9 -1
- package/dist/skills/legion-architect/references/wake-routing.md +1 -1
- package/dist/skills/legion-controller/references/admission.md +8 -8
- package/dist/skills/legion-worker/references/findings.md +17 -13
- package/dist/skills/legion-worker/references/tools.md +3 -2
- package/package.json +1 -1
|
@@ -38,6 +38,8 @@ You own one issue tree from its first decision to the merge that closes it. The
|
|
|
38
38
|
- On each `child-closed`, read the child's handoff. Edit the spec of each open child the result changes, and take out each child it makes unneeded with `park_child` and say why with `dispatch comment`.
|
|
39
39
|
- Before you park a child for good (one made unneeded, or parked so its tree can finish), set the `--blocked-by` list of each sibling that waits on it again without it (one call with the rest of its list, or `--clear-blocked-by` when it was the only one), or park that sibling too: a parked child is stopped, not done, and its dependents stay held with no notice. A park followed by `rerun_child` keeps its dependents' links: they wait through the rerun and start when the rerun's merge closes the child.
|
|
40
40
|
- A released child runs in your tree's admission slot, never its own, and never becomes a root while your tree is live.
|
|
41
|
+
- A root that waited in the admission queue, never ran and never left another tree joins your tree once a person makes it your child, if it is `todo`, and otherwise at your release of it (the `child-status` row of [wake routing](skill://legion-architect/references/wake-routing.md)); once in, it is held for its blockers like any child you release. A root that left another tree, handed over by its finished tree or admitted as an orphan, stays its own tree and never joins yours, even one that was your root's child before your root was admitted again. A labelled `todo` issue under a child you have not released, unless it ran as a tree of its own or left another tree, is held under that unreleased child (not a blocked-by hold): it waits for no slot until your release of it or of that child brings it in, with any `todo` child of its own.
|
|
42
|
+
- A release that cannot take a child in is refused 409 and writes nothing, its message naming the child and why: release the rest of the wave again without it. `CHILD_NOT_ADOPTABLE` is an issue that runs or ran as a tree of its own, carries a run handed over to it, or was handed over (or admitted as an orphan) as a root of its own: leave it there, or ask the controller. `CHILD_IN_OTHER_TREE` is another tree's child. When the tree it names is a root held under an unreleased child of yours (a root that queued and never ran, so it has no architect of its own), release that root, or the unreleased child it sits under, instead: its children come with it. Otherwise re-parent the child back in Dispatch, or ask that tree's architect or the controller.
|
|
41
43
|
|
|
42
44
|
## 3. Children complete
|
|
43
45
|
|
|
@@ -27,10 +27,18 @@ child waits in your tree until Legion starts it.
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
dispatch issue --project <project> --parent <root issue> --title '<child outcome>' --spec-file - <<'EOF'
|
|
30
|
-
<
|
|
30
|
+
<the child's spec, written as skill://dispatch-writing-specs says, scaled to the child>
|
|
31
31
|
EOF
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
- Write each child's spec as `skill://dispatch-writing-specs` says, scaled to the child: its
|
|
35
|
+
outline (`Summary` through `Acceptance`, a few sentences a part for a small child), a proposed
|
|
36
|
+
answer to each point, each term a new reader may not know explained, no item number from another
|
|
37
|
+
document (name a requirement of the root by what it says), and no text copied from the root that
|
|
38
|
+
does not apply to this child. The child's workers read only this spec.
|
|
39
|
+
- Before `dispatch issue` creates each child, paste its whole spec into a fresh
|
|
40
|
+
`task(agent="plan-gap-analyst")` to check it against `skill://dispatch-writing-specs`, and fix
|
|
41
|
+
what it flags: your own reread misses the terms and item numbers you already know.
|
|
34
42
|
- `--project` is the issue key's prefix before `-<n>` (`LEGSMOKE-3` → `LEGSMOKE`).
|
|
35
43
|
- In a root session `$LEGION_ISSUE` is the root (it equals `$LEGION_TREE`): pass it as `--parent`.
|
|
36
44
|
The daemon makes the sub-issue link from `--parent`.
|
|
@@ -19,7 +19,7 @@ and 7 (a conflict, the hand-over, the close) is in
|
|
|
19
19
|
| Wake | Procedure |
|
|
20
20
|
| --- | --- |
|
|
21
21
|
| `carried-gate-opened` | Only a root whose catch-up said `carried` gets it. Its `version` and `reason`: a human approved the old root's spec document at `version`, which opened the gate this root carried; the daemon has released any READY it refused and started any child waiting on it. It is not `design-approved`: do not proceed to section 2 or release a wave because of it, and start nothing. |
|
|
22
|
-
| `child-status` | A child of your tree left the workflow or re-entered it; the reason names the child and its new status
|
|
22
|
+
| `child-status` | A child of your tree left the workflow or re-entered it, or joined your tree from the admission queue; the reason names the child and its new status, or reads `<KEY> joined the tree of <ROOT> from the admission queue`. `todo` (a human's move, your `release_children`, or your `rerun_child`) means it runs again under your tree from planning, and the daemon starts it; you start nothing. A child held for a blocker starts the same way once nothing holds it, and the reason, naming it and its root, says what cleared the hold: its last blocker's close, naming the issues it waited on, now done, or a person or you taking its blocked-by links off; you start nothing for it either. `backlog`, `icebox` or `triage` (a human's move, or your `park_child`) means the daemon has suspended its workers, and it advances no further until it is set back to `todo`. Joined from the admission queue means a root that waited for a slot and never ran, which a person made a child of your tree or your `release_children` adopted, now runs in your tree with no slot or architect of its own, from planning when it is `todo` and parked otherwise; one that waits on an unfinished blocked-by issue is held for that blocker like any other child, and starts when nothing holds it; you start nothing. What the rest of the tree does is your decision. |
|
|
23
23
|
| `child-closed` | Read the child completion and remaining open children. Re-scope open work, park obsolete work for good with `park_child` (first take its link off each sibling that waits on it, or park that sibling too, as section 2 says), and file any new child the result calls for and release it at once with `release_children`, blocked by what it builds on (section 2). When a worker waits on this child for a missing surface (see `phase-finished`), tell it to continue with `envoy_publish` to its role topic. The last child's close is not the end-game (section 3). |
|
|
24
24
|
| `child-release-stalled` | Its `reason` names a child your `release_children` released while Dispatch already showed it `todo`, and that child's parent, whose release has not reached the daemon after three tries. Read the parent's record with the `legion` tool's `read_record` (`issue` the parent); run `release_children` for the child again once the parent is recorded in your tree, and tell the controller if it never is. |
|
|
25
25
|
| `child-not-recorded` | Its `reason` names a child your tree did not record and why: its repository resolves to none (neither it nor an ancestor names one, and the project has no default), or to one not mapped to the project, or to one the daemon leaves out for a missing GitHub App. The daemon said why on the child too. Set the child's repository to one of the project's (`dispatch issue-update --repo owner/name`), then release it again with `release_children`; tell the controller when the repository it needs is not served. |
|
|
@@ -7,16 +7,16 @@ waits, or neither. Read its key against `admission` and its tree's root.
|
|
|
7
7
|
| What `read_state` shows | What it means | What you do |
|
|
8
8
|
|---|---|---|
|
|
9
9
|
| The key is in `admission.active` | A root holding a slot: its tree runs, `admitted` until its architect starts the first phase | Nothing, beyond [trees waiting on a root claim](skill://legion-controller/SKILL.md#trees-waiting-on-a-root-claim) |
|
|
10
|
-
| The key is in `admission.waiting` and not in `admission.blocked` | A root handed to Legion in `todo`, queued for the next free slot: a root a person answered while it waited in `awaiting_person` comes first, oldest answer first, then every root that never ran, in Dispatch rank order | Nothing: it takes the next free slot by itself |
|
|
10
|
+
| The key is in `admission.waiting` and not in `admission.blocked` | A root handed to Legion in `todo`, queued for the next free slot: a root a person answered while it waited in `awaiting_person` comes first, oldest answer first, then every root that never ran, in Dispatch rank order. A root that left another tree (handed over by its finished tree, or admitted as an orphan) waits here as its own root even under a live tree, the old root's return included: no tree adopts it | Nothing: it takes the next free slot by itself |
|
|
11
11
|
| `phase: awaiting_person`, `waitingOn` | A root that already ran and now waits only on a person: an answer to its architect's question (`waitingOn.kind` `ask`) or a review of its spec (`gate`). It holds no slot, its architect session is suspended, and its tree stays live. Unanswered, it is in neither list; `waitingOn.answeredAt` means the daemon has promoted it to the front of `admission.waiting` | Nothing: it is not something to admit, label or park, and the slot it returned is no reason to take an issue ([Free slots](skill://legion-controller/SKILL.md#free-slots)). The daemon resumes it in its own architect session at the next free slot. If its label goes or a person or outside session claims it on Dispatch, the daemon sends `unslotted` and does not resume it |
|
|
12
12
|
| The key is in `admission.waiting` and in `admission.blocked` | A root in the line that waits on the Dispatch issues `admission.blocked` names: admission passes it over, and it takes no slot, until every one of them is `done` | Nothing: the wait ends when each blocker reaches `done` (a person's close, or the blocker's own merge) or its link is taken off (by a person or the tree's architect). Name the wait in the day's report |
|
|
13
|
-
| `phase: admitted`, in neither list, and Dispatch shows a `child_of` parent | A child: it runs or waits with its tree, the root its `child_of` chain reaches. Under a root whose `phase` is `done` it waits with it | Leave it to its tree. It runs again when its root does, or as a root of its own once it is `todo` with the `legion` label |
|
|
13
|
+
| `phase: admitted`, in neither list, and Dispatch shows a `child_of` parent | A child: it runs or waits with its tree, the root its `child_of` chain reaches. Under a root whose `phase` is `done` it waits with it. A labelled `todo` issue here is not in the line either: one whose recorded parent is in a live tree runs in that tree (the daemon adopted it there), or is held with that parent while the parent itself is held under an unreleased child, and one whose parent is not recorded but sits under a live tree is held under an unreleased child of that tree until its architect releases it or its parent. That hold is not `admission.blocked`, which names only blocked-by links | Leave it to its tree. It runs again when its root does, or as a root of its own once it is `todo` with the `legion` label and no live tree is above it |
|
|
14
14
|
| `phase: admitted`, `status: todo`, in neither list, no parent | A root a person took out of the line by taking its label off | Nothing: the label puts it back in the line, and a person's label is their decision |
|
|
15
15
|
| `phase: done` while `status` is `in_progress`, `testing`, `needs_review` or `retro` | Legion is not running it under that status, and it sent the `unslotted` wake. Either someone other than Legion moved a root that waited for a slot there, and the daemon took it out of the workflow at that move since no slot would ever reach it; or a root waiting on a person could not be resumed — its `legion` label is gone, or a person or an outside session took its Dispatch claim — and the daemon took it out the same way, leaving the `in_progress` it ran with. A parked child stays parked. Legion starts nothing for any of them | Re-admit nothing yourself: `dispatch read` shows who works it now. Name it in your summary; `todo` with the `legion` label queues it again |
|
|
16
16
|
|
|
17
|
-
A root in the workflow with no slot that is in neither `admission.waiting
|
|
18
|
-
row above does not stay that way: every pass of admission (a Dispatch
|
|
19
|
-
read, its tick) takes it out of the workflow and sends the `unslotted`
|
|
20
|
-
`awaiting_person` root only when its label or its Dispatch claim makes a
|
|
21
|
-
only, so a controller that starts later finds such a root by the
|
|
22
|
-
does.
|
|
17
|
+
A root in the workflow with no slot that is in neither `admission.waiting`, nor the label-removed
|
|
18
|
+
row above, nor `todo` under a live tree does not stay that way: every pass of admission (a Dispatch
|
|
19
|
+
event, the daemon's boot read, its tick) takes it out of the workflow and sends the `unslotted`
|
|
20
|
+
wake — an unanswered `awaiting_person` root only when its label or its Dispatch claim makes a
|
|
21
|
+
resume unsafe. The wake is live only, so a controller that starts later finds such a root by the
|
|
22
|
+
last row, as its start procedure does.
|
|
@@ -57,7 +57,8 @@ says which), its first line exactly `Clear defect from <your role token>`. It pr
|
|
|
57
57
|
`expects_reply: none`. It holds:
|
|
58
58
|
|
|
59
59
|
- your role token, from your `Legion addressing` line
|
|
60
|
-
- the defect,
|
|
60
|
+
- the defect: what went wrong, where and to whom, with the numbers, and the issue it came from
|
|
61
|
+
(`dispatch://<KEY>`)
|
|
61
62
|
- where the fix belongs: the repository and the component
|
|
62
63
|
- the fix
|
|
63
64
|
- the evidence comment, `dispatch://<REPORT KEY>/comment/<id>`
|
|
@@ -132,23 +133,26 @@ check's `Production:` line then names the finding as sent to the controller, or
|
|
|
132
133
|
|
|
133
134
|
## What the ask says
|
|
134
135
|
|
|
135
|
-
The question stands alone, since the ask view shows no comment. It holds at most
|
|
136
|
+
The question stands alone, since the ask view shows no comment. It holds at most 2,000 characters,
|
|
136
137
|
the `Ref: <reference>` line `--ref` appends included (about 75 characters for a comment's
|
|
137
138
|
reference). Its first line names who asks: `Clear defect from <your role token>` for a clear
|
|
138
139
|
defect no controller took, else `Finding from <your role token>`. The architect's acceptance and the
|
|
139
|
-
controller's catch-up find a finding ask by that line. Then it
|
|
140
|
+
controller's catch-up find a finding ask by that line. Then it names the concrete case before any
|
|
141
|
+
general statement of it:
|
|
140
142
|
|
|
141
|
-
-
|
|
142
|
-
|
|
143
|
+
- what went wrong, where and to whom: the issue it came from (`dispatch://<KEY>`), the machine,
|
|
144
|
+
file, command or session, and the numbers;
|
|
145
|
+
- where the fix would belong: the repository and component, and a plain statement that it is not
|
|
143
146
|
Legion's when it is not. A problem is not Legion's because you work in Legion: name the
|
|
144
147
|
component that misbehaved;
|
|
145
|
-
- the decision a person must make,
|
|
146
|
-
controller took carries the fix instead, and its
|
|
147
|
-
`Hand it to the owning tree` first and recommended.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
comment <id>`, and cite that comment with `--ref`, the one reference an ask
|
|
148
|
+
- the decision a person must make, what happens to whom under each option, and your
|
|
149
|
+
recommendation and its reason. A clear defect no controller took carries the fix instead, and its
|
|
150
|
+
options ask where the work goes, with `Hand it to the owning tree` first and recommended.
|
|
151
|
+
|
|
152
|
+
Evidence the decision does not need (full command output, logs, every file and line, the pull
|
|
153
|
+
request) goes in a comment. Post it first as a `dispatch comment` on the issue the ask goes on,
|
|
154
|
+
which prints `Posted comment <id>`, and cite that comment with `--ref`, the one reference an ask
|
|
155
|
+
takes. That issue,
|
|
152
156
|
`<ASK KEY>` below, is the report issue, except as [When no controller takes
|
|
153
157
|
it](#when-no-controller-takes-it) says:
|
|
154
158
|
|
|
@@ -164,7 +168,7 @@ dispatch ask --issue <ASK KEY> --ref 'dispatch://<ASK KEY>/comment/<id>' --quest
|
|
|
164
168
|
--option 'File it for Legion: Legion works it once it is filed' \
|
|
165
169
|
--option 'Do not file: <what stays as it is>' <<'EOF'
|
|
166
170
|
Finding from <your role token>
|
|
167
|
-
<
|
|
171
|
+
<what went wrong, where and to whom, with dispatch://<KEY> and the numbers; where the fix belongs, and that it is not Legion's when it is not; what each option does to whom; your recommendation and why>
|
|
168
172
|
EOF
|
|
169
173
|
```
|
|
170
174
|
|
|
@@ -14,8 +14,9 @@ which you have; those need no runner.
|
|
|
14
14
|
- `psql` — the Dispatch browser suite (`bun run e2e`) resets its database for every spec through
|
|
15
15
|
`packages/dispatch/e2e/psql.ts`, which `seed.ts` calls, and the local stack (`bun run
|
|
16
16
|
dispatch:local`, `packages/dispatch/e2e/local-instance.ts`) refuses to start without `go`,
|
|
17
|
-
`psql`, `flock` and `
|
|
18
|
-
given. The image carries `go`, `flock` and `
|
|
17
|
+
`psql`, `flock`, `openssl` and `python3` on `PATH`, and without `docker` too unless a
|
|
18
|
+
`DATABASE_URL` is given. The image carries `go`, `flock`, `openssl` and `python3`, a
|
|
19
|
+
`DATABASE_URL` stands in for `docker`,
|
|
19
20
|
and `psql` was the one a role had no way to supply — so a role whose change owes that suite can
|
|
20
21
|
run it.
|
|
21
22
|
- `redis-cli` — no repository of the project speaks Redis today; it is carried anyway, at about a
|