@sjawhar/pi-legion 10.19.11 → 10.20.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
CHANGED
|
@@ -14349,6 +14349,7 @@ var SESSION_ID_PATTERN = "[^/?#\\s\\p{Z}\\p{Cc}<>\"'`\\[\\]|]+";
|
|
|
14349
14349
|
var sessionIdOnly = new RegExp(`^${SESSION_ID_PATTERN}$`, "u");
|
|
14350
14350
|
// ../contracts/src/dispatch-tools.ts
|
|
14351
14351
|
var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference. An external reference addresses an existing Dispatch issue, including one linked to that GitHub pull request; only dispatch issue with --external creates a native issue.";
|
|
14352
|
+
var BOARD_NEIGHBOUR_REFUSAL = "The server refuses a key that does not exist, one in another project, this issue itself, an empty value, and a pair the board does not hold in that order.";
|
|
14352
14353
|
var OWNER_REFERENCE = "Exactly one of issue and project is required. An issue is a native KEY or external owner/repo#n reference; a project is a project key such as CORE and addresses an unlinked project document named by artifact.";
|
|
14353
14354
|
var ASK_QUESTION_CONTRACT = "The question carries the problem the reader recognises and why it matters now, what constrains " + "the answer, and the recommendation with its reason. It asks how to solve the problem or which " + "outcome is wanted; never enumerate choices in the question.";
|
|
14354
14355
|
var ASK_OPTIONS_CONTRACT = "Options carry the genuinely different approaches. Each option has a label, and its description " + "says what that approach costs.";
|
|
@@ -14388,7 +14389,7 @@ var commentValidation = {
|
|
|
14388
14389
|
},
|
|
14389
14390
|
message: `${commentOwner.message} turn requires reply_to_ask.`
|
|
14390
14391
|
};
|
|
14391
|
-
var ISSUE_UPDATE_FIELDS_RULE = "Issue update requires at least one field besides issue: status, title, labels, priority, external_links, route, parent, blocked_by, components, or
|
|
14392
|
+
var ISSUE_UPDATE_FIELDS_RULE = "Issue update requires at least one field besides issue: status, title, labels, priority, external_links, route, parent, blocked_by, components, repo, before, or after.";
|
|
14392
14393
|
var ISSUE_UPDATE_DONE_RULE = "status done requires reason, a non-empty note saying why the issue is closing, posted on the issue before it closes because a closed issue refuses messages, comments, and artifacts";
|
|
14393
14394
|
var ISSUE_UPDATE_REASON_RULE = "reason goes only with status done";
|
|
14394
14395
|
var ISSUE_UPDATE_RULE = `${ISSUE_UPDATE_FIELDS_RULE} ${ISSUE_UPDATE_DONE_RULE}; ${ISSUE_UPDATE_REASON_RULE}.`;
|
|
@@ -14402,7 +14403,7 @@ function issueUpdateProblem(value) {
|
|
|
14402
14403
|
const status = typeof input.status === "string" ? `status ${input.status}` : "an update without status done";
|
|
14403
14404
|
return `${ISSUE_UPDATE_REASON_RULE}: it is the note posted on the issue as it closes, and ${status} closes nothing. Drop reason, or set status done to close the issue.`;
|
|
14404
14405
|
}
|
|
14405
|
-
const changesAField = typeof input.status === "string" || typeof input.title === "string" || Array.isArray(input.labels) || typeof input.priority === "number" || input.priority === null || Array.isArray(input.external_links) || typeof input.route === "string" || typeof input.parent === "string" || Array.isArray(input.blocked_by) || typeof input.components === "object" && input.components !== null || typeof input.repo === "string";
|
|
14406
|
+
const changesAField = typeof input.status === "string" || typeof input.title === "string" || Array.isArray(input.labels) || typeof input.priority === "number" || input.priority === null || Array.isArray(input.external_links) || typeof input.route === "string" || typeof input.parent === "string" || Array.isArray(input.blocked_by) || typeof input.components === "object" && input.components !== null || typeof input.repo === "string" || typeof input.before === "string" || typeof input.after === "string";
|
|
14406
14407
|
return changesAField ? undefined : ISSUE_UPDATE_FIELDS_RULE;
|
|
14407
14408
|
}
|
|
14408
14409
|
var messageValidation = {
|
|
@@ -14487,10 +14488,10 @@ var dispatchToolSpecs = [
|
|
|
14487
14488
|
name: "dispatch_issue_update",
|
|
14488
14489
|
example: {
|
|
14489
14490
|
issue: "DSP-1",
|
|
14490
|
-
|
|
14491
|
-
|
|
14491
|
+
priority: 1,
|
|
14492
|
+
before: "DSP-2"
|
|
14492
14493
|
},
|
|
14493
|
-
description: "Update an existing issue: move its lifecycle status, retitle it, replace its labels, set " + "its priority, link a URL (the pull request that delivers it, a run, a document), set its " + "route, set or clear its parent, replace the issues it is blocked by, attach it to " + "architecture components,
|
|
14494
|
+
description: "Update an existing issue: move its lifecycle status, retitle it, replace its labels, set " + "its priority, link a URL (the pull request that delivers it, a run, a document), set its " + "route, set or clear its parent, replace the issues it is blocked by, attach it to " + "architecture components, set the repository it targets, or move it on its project's " + "board. Status is one of " + `${ISSUE_STATUSES.join(", ")}; outside Legion, move it yourself as the work advances; inside ` + "Legion the daemon moves it. A non-empty external_links is " + "merged into the issue's existing links by URL, so linking the pull request you just opened " + "keeps every earlier link; an empty external_links removes every link instead. components " + "replaces the issue's own attachment. Closing an issue " + "(status done) requires reason, the note that says why: it is posted on the issue as a " + "message, then the issue closes, because a closed issue refuses messages, comments, and " + "artifacts; reason goes only with status done. A closed issue takes only a board move " + "(before, after), components, " + "a reopening status (any status but done), and an external_links write that adds no new " + "link (so a link can move to the issue that replaced it); everything else, priority " + "included, waits for the reopen. " + "priority is yours to set and a human overrides it. before and after move the issue on " + "its project's board: before puts it above that issue, after below, and both together " + "land it between them. A project's board order is one agent's to keep; in a Legion " + "deployment that is the controller. At least one " + `field besides issue is required. ${ISSUE_REFERENCE}`,
|
|
14494
14495
|
arguments: (z2) => ({
|
|
14495
14496
|
issue: z2.string().describe(ISSUE_REFERENCE),
|
|
14496
14497
|
status: z2.enum(ISSUE_STATUSES).describe("New lifecycle status.").optional(),
|
|
@@ -14503,7 +14504,9 @@ var dispatchToolSpecs = [
|
|
|
14503
14504
|
parent: z2.string().describe("Parent issue key in the same project; an empty string clears the parent.").optional(),
|
|
14504
14505
|
blocked_by: z2.array(z2.string({ min: 1 }), { max: MAX_ISSUE_BLOCKERS }).describe("Replacement list of issue keys in the same project this issue waits on; [] clears it. Dispatch refuses a dependency cycle.").optional(),
|
|
14505
14506
|
components: componentsArgument(z2).optional(),
|
|
14506
|
-
repo: z2.string().describe("The repository the issue targets, owner/name, mapped to the issue's project in Settings; an empty string clears it, so the issue inherits its parent's or the project's default again.").optional()
|
|
14507
|
+
repo: z2.string().describe("The repository the issue targets, owner/name, mapped to the issue's project in Settings; an empty string clears it, so the issue inherits its parent's or the project's default again.").optional(),
|
|
14508
|
+
before: z2.string().describe(`Move the issue above this issue on its project's board: an issue key in the same project. With after, the issue lands between the two. ${BOARD_NEIGHBOUR_REFUSAL}`).optional(),
|
|
14509
|
+
after: z2.string().describe(`Move the issue below this issue on its project's board: an issue key in the same project. With before, the issue lands between the two. ${BOARD_NEIGHBOUR_REFUSAL}`).optional()
|
|
14507
14510
|
}),
|
|
14508
14511
|
validation: {
|
|
14509
14512
|
check: (value) => issueUpdateProblem(value) === undefined,
|
|
@@ -16932,7 +16935,7 @@ async function bootLegionClaim(host2) {
|
|
|
16932
16935
|
// package.json
|
|
16933
16936
|
var package_default = {
|
|
16934
16937
|
name: "@sjawhar/pi-legion",
|
|
16935
|
-
version: "10.
|
|
16938
|
+
version: "10.20.0",
|
|
16936
16939
|
license: "Apache-2.0",
|
|
16937
16940
|
type: "module",
|
|
16938
16941
|
omp: {
|
|
@@ -59,7 +59,7 @@ The controller is the project's order keeper. It retains its startup role,
|
|
|
59
59
|
`legion-<project>-controller`; `backlog-order` is retired. Send READY packets, scope questions,
|
|
60
60
|
and routing requests to `notifications.role.legion-<project>-controller`, then follow
|
|
61
61
|
[Backlog stewardship](skill://legion-controller/references/backlog-stewardship.md) for daily
|
|
62
|
-
weekly-plan reconciliation,
|
|
62
|
+
weekly-plan reconciliation, a person's rulings, ownership routing, and stopped-session recovery.
|
|
63
63
|
These duties change Dispatch's priority and board-rank data and route plan work to a live session;
|
|
64
64
|
they start nothing on Legion and hand it no issue ([Free slots](#free-slots-go-daemon)).
|
|
65
65
|
|
|
@@ -365,9 +365,9 @@ themselves: an issue reaches Legion only when a person hands it over
|
|
|
365
365
|
|
|
366
366
|
- **Direct user message always first.** If this turn includes a direct user message, answer
|
|
367
367
|
it before handling every other wake.
|
|
368
|
-
- **
|
|
369
|
-
the full [Backlog stewardship](#backlog-stewardship) reconciliation and
|
|
370
|
-
in the weekly plan.
|
|
368
|
+
- **A person's rulings.** A direct Dispatch message to this controller from a person is a ruling:
|
|
369
|
+
after answering it, run the full [Backlog stewardship](#backlog-stewardship) reconciliation and
|
|
370
|
+
record the current rule in the weekly plan.
|
|
371
371
|
- **One wake = one turn.** Handle exactly the wake's implication, then end the turn. Never
|
|
372
372
|
poll, idle-loop, or wait for another event. Two additions, after any direct user message: every
|
|
373
373
|
turn first rechecks the [trees waiting on a root
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Backlog stewardship
|
|
2
2
|
|
|
3
3
|
The controller keeps the Dispatch backlog's facts aligned with the deployment's current weekly
|
|
4
|
-
plan. The plan is the source of the work order and its one-owner map; Dispatch
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
plan. The plan is the source of the work order and its one-owner map; Dispatch board rank is the
|
|
5
|
+
executable form of that order. The deployment instructions name the weekly-planning issue and its
|
|
6
|
+
`plan-week-*` artifact.
|
|
7
7
|
|
|
8
8
|
## Controller routing address
|
|
9
9
|
|
|
@@ -14,16 +14,17 @@ subscription: changing roles ends the controller's wake delivery.
|
|
|
14
14
|
|
|
15
15
|
## Reconcile the weekly plan
|
|
16
16
|
|
|
17
|
-
Run this pass on the first turn of every UTC day and after every ruling from
|
|
17
|
+
Run this pass on the first turn of every UTC day and after every ruling from a person:
|
|
18
18
|
|
|
19
19
|
1. Read the weekly-planning issue and select its newest `plan-week-*` artifact by its latest
|
|
20
20
|
`artifact.version` event. Read that artifact before changing any issue.
|
|
21
|
-
2. For every current plan line in this deployment's project, make
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
2. For every current plan line in this deployment's project, make the project's board order match
|
|
22
|
+
the line order exactly: Legion admits waiting roots by board rank alone — unlike the ready order
|
|
23
|
+
an agent takes its own next issue by, which is priority, then board rank — so board rank is what
|
|
24
|
+
carries the plan's order. Set the coarse priority too, as the signal people and filters read; it
|
|
25
|
+
changes no order. Keep each line's own stated sequence. Do not invent a second order from a
|
|
26
|
+
title, a stale route, or an instruction. Reorder with
|
|
27
|
+
`dispatch issue-update --issue <KEY> --before <OTHER>` or `--after <OTHER>`.
|
|
27
28
|
3. Reconcile the plan's one-owner map. For each listed owner, verify the named session is live.
|
|
28
29
|
For unowned work, find a suitable live owner with `envoy_sessions` filtered by `title` or `dir`,
|
|
29
30
|
route the issue to that exact session, and tell it what it owns. Routing hands the work to that
|
|
@@ -33,9 +34,10 @@ Run this pass on the first turn of every UTC day and after every ruling from Sam
|
|
|
33
34
|
`dispatch doc-read`. The artifact states the current rule; replace superseded text instead of
|
|
34
35
|
keeping a change log in it. A comment or message does not update the one-owner map.
|
|
35
36
|
|
|
36
|
-
A ruling from
|
|
37
|
-
scope or priority decision, then record the resulting current rule in the affected weekly-plan
|
|
38
|
-
(or its ruling section when it has no one line). Link the message when Dispatch gave it a
|
|
37
|
+
A ruling from a person is a direct Dispatch message to this controller. Answer it first, carry out
|
|
38
|
+
its scope or priority decision, then record the resulting current rule in the affected weekly-plan
|
|
39
|
+
row (or its ruling section when it has no one line). Link the message when Dispatch gave it a
|
|
40
|
+
reference.
|
|
39
41
|
A ruling triggers the full reconciliation pass even when it appears to affect only one issue.
|
|
40
42
|
|
|
41
43
|
## Answering controller deliveries
|