@sjawhar/pi-legion-envoy 5.13.0 → 5.14.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/envoy.js +15 -6
- package/dist/legion.js +4 -3
- package/dist/skills/dispatch/SKILL.md +40 -2
- package/package.json +1 -1
package/dist/envoy.js
CHANGED
|
@@ -30369,13 +30369,14 @@ var dispatchToolSpecs = [
|
|
|
30369
30369
|
},
|
|
30370
30370
|
{
|
|
30371
30371
|
name: "dispatch_issues",
|
|
30372
|
-
example: { project: "AGENTC" },
|
|
30373
|
-
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, or how recently it changed
|
|
30372
|
+
example: { project: "AGENTC", priority: [0, 1] },
|
|
30373
|
+
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, priority, or how recently it " + "changed; priority takes one or more of 0-3 (P0-P3) and null for an issue with no priority, so " + "an owner's P0/P1 audit is priority [0, 1]. Do not use it to search by keyword or phrase; " + "dispatch_search remains the keyword surface. Rows are capped at limit (default 50, max 250), " + "applied to the response here, not by the server.",
|
|
30374
30374
|
arguments: (z2) => ({
|
|
30375
30375
|
project: z2.string().describe("Project key to list issues from."),
|
|
30376
30376
|
status: z2.enum(ISSUE_STATUSES).describe("Optional lifecycle status filter.").optional(),
|
|
30377
30377
|
parent: z2.string().describe("Optional parent issue key filter.").optional(),
|
|
30378
30378
|
label: z2.string().describe("Optional label filter.").optional(),
|
|
30379
|
+
priority: z2.array(z2.number({ int: true, min: 0, max: 3 }).nullable(), { min: 1, max: 5 }).describe("Optional priority filter: one or more of 0 (P0, highest) through 3 (P3, lowest), and null " + "for an issue with no priority; an issue matching any listed value is returned.").optional(),
|
|
30379
30380
|
updated_since: z2.string().describe("Optional RFC3339 timestamp; only issues updated at or after it.").optional(),
|
|
30380
30381
|
limit: z2.number({ int: true, min: 1, max: 250 }).describe("Maximum rows, 1-250; default 50.").optional()
|
|
30381
30382
|
})
|
|
@@ -32547,6 +32548,9 @@ class DispatchClient {
|
|
|
32547
32548
|
for (const [name, value] of Object.entries(query)) {
|
|
32548
32549
|
if (typeof value === "string" || typeof value === "number") {
|
|
32549
32550
|
url2.searchParams.set(name, String(value));
|
|
32551
|
+
} else if (Array.isArray(value)) {
|
|
32552
|
+
for (const item of value)
|
|
32553
|
+
url2.searchParams.append(name, String(item));
|
|
32550
32554
|
}
|
|
32551
32555
|
}
|
|
32552
32556
|
}
|
|
@@ -32824,6 +32828,10 @@ function optionalPriority(args, name) {
|
|
|
32824
32828
|
return null;
|
|
32825
32829
|
return typeof value === "number" ? value : undefined;
|
|
32826
32830
|
}
|
|
32831
|
+
function optionalPriorityFilter(args, name) {
|
|
32832
|
+
const value = args[name];
|
|
32833
|
+
return Array.isArray(value) ? value.map((item) => item ?? "none") : undefined;
|
|
32834
|
+
}
|
|
32827
32835
|
function optionalComponents(args, name) {
|
|
32828
32836
|
const value = args[name];
|
|
32829
32837
|
if (typeof value !== "object" || value === null)
|
|
@@ -32850,12 +32858,11 @@ async function architectureGuidance(client, project, components) {
|
|
|
32850
32858
|
if (components.mode === "none" || components.ids.length > 0)
|
|
32851
32859
|
return;
|
|
32852
32860
|
try {
|
|
32853
|
-
await client.getArchitectureSource(project)
|
|
32854
|
-
return `Project ${project} has an architecture model, but this issue is not linked to any of its current components. ${architectureComponentsAction}`;
|
|
32855
|
-
} catch (error48) {
|
|
32856
|
-
if (error48 instanceof DispatchServiceError && error48.status === 404 && error48.code === "SOURCE_NOT_FOUND") {
|
|
32861
|
+
if (await client.getArchitectureSource(project) === null) {
|
|
32857
32862
|
return;
|
|
32858
32863
|
}
|
|
32864
|
+
return `Project ${project} has an architecture model, but this issue is not linked to any of its current components. ${architectureComponentsAction}`;
|
|
32865
|
+
} catch (error48) {
|
|
32859
32866
|
return `Could not check whether project ${project} has an architecture model: ${messageFor(error48)}. ${architectureComponentsAction}`;
|
|
32860
32867
|
}
|
|
32861
32868
|
}
|
|
@@ -33890,6 +33897,7 @@ async function executeDispatchTool(input) {
|
|
|
33890
33897
|
const status = optionalString(args, "status");
|
|
33891
33898
|
const parent = optionalString(args, "parent");
|
|
33892
33899
|
const label = optionalString(args, "label");
|
|
33900
|
+
const priority = optionalPriorityFilter(args, "priority");
|
|
33893
33901
|
const updatedSince = optionalString(args, "updated_since");
|
|
33894
33902
|
const limit = Math.min(Math.max(optionalNumber(args, "limit") ?? 50, 1), 250);
|
|
33895
33903
|
const issues = await client.listIssues({
|
|
@@ -33897,6 +33905,7 @@ async function executeDispatchTool(input) {
|
|
|
33897
33905
|
...status === undefined ? {} : { status },
|
|
33898
33906
|
...parent === undefined ? {} : { parent },
|
|
33899
33907
|
...label === undefined ? {} : { label },
|
|
33908
|
+
...priority === undefined ? {} : { priority },
|
|
33900
33909
|
...updatedSince === undefined ? {} : { updated_since: updatedSince }
|
|
33901
33910
|
});
|
|
33902
33911
|
const rows = issues.slice(0, limit).map((row) => ({
|
package/dist/legion.js
CHANGED
|
@@ -16192,7 +16192,7 @@ import { logger } from "@oh-my-pi/pi-utils";
|
|
|
16192
16192
|
// package.json
|
|
16193
16193
|
var package_default = {
|
|
16194
16194
|
name: "@sjawhar/pi-legion-envoy",
|
|
16195
|
-
version: "5.
|
|
16195
|
+
version: "5.14.0",
|
|
16196
16196
|
type: "module",
|
|
16197
16197
|
omp: {
|
|
16198
16198
|
extensions: [
|
|
@@ -30492,13 +30492,14 @@ var dispatchToolSpecs = [
|
|
|
30492
30492
|
},
|
|
30493
30493
|
{
|
|
30494
30494
|
name: "dispatch_issues",
|
|
30495
|
-
example: { project: "AGENTC" },
|
|
30496
|
-
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, or how recently it changed
|
|
30495
|
+
example: { project: "AGENTC", priority: [0, 1] },
|
|
30496
|
+
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, priority, or how recently it " + "changed; priority takes one or more of 0-3 (P0-P3) and null for an issue with no priority, so " + "an owner's P0/P1 audit is priority [0, 1]. Do not use it to search by keyword or phrase; " + "dispatch_search remains the keyword surface. Rows are capped at limit (default 50, max 250), " + "applied to the response here, not by the server.",
|
|
30497
30497
|
arguments: (z2) => ({
|
|
30498
30498
|
project: z2.string().describe("Project key to list issues from."),
|
|
30499
30499
|
status: z2.enum(ISSUE_STATUSES).describe("Optional lifecycle status filter.").optional(),
|
|
30500
30500
|
parent: z2.string().describe("Optional parent issue key filter.").optional(),
|
|
30501
30501
|
label: z2.string().describe("Optional label filter.").optional(),
|
|
30502
|
+
priority: z2.array(z2.number({ int: true, min: 0, max: 3 }).nullable(), { min: 1, max: 5 }).describe("Optional priority filter: one or more of 0 (P0, highest) through 3 (P3, lowest), and null " + "for an issue with no priority; an issue matching any listed value is returned.").optional(),
|
|
30502
30503
|
updated_since: z2.string().describe("Optional RFC3339 timestamp; only issues updated at or after it.").optional(),
|
|
30503
30504
|
limit: z2.number({ int: true, min: 1, max: 250 }).describe("Maximum rows, 1-250; default 50.").optional()
|
|
30504
30505
|
})
|
|
@@ -286,16 +286,54 @@ distinction from the named issue, citing it (`dispatch://KEY`), for whoever read
|
|
|
286
286
|
|
|
287
287
|
To see the shape of a project rather than find a phrase, list its issues:
|
|
288
288
|
```ts
|
|
289
|
-
dispatch_issues({ project, status?, parent?, label?, updated_since?, limit? })
|
|
289
|
+
dispatch_issues({ project, status?, parent?, label?, priority?, updated_since?, limit? })
|
|
290
290
|
```
|
|
291
291
|
Each row carries the issue key, title, status, priority, parent, labels, its open-ask count, and
|
|
292
292
|
when it last changed — a roadmap or backlog pass without opening every issue. Filter with `status`
|
|
293
|
-
(a lifecycle status), `parent` (one issue's children), `label`,
|
|
293
|
+
(a lifecycle status), `parent` (one issue's children), `label`, `priority` (a list of `0`–`3`, with
|
|
294
|
+
`null` for an issue with no priority: `[0, 1]` is every P0 and P1), or `updated_since` (an RFC3339
|
|
294
295
|
timestamp, for "what moved this week"). `limit` caps the rows at 50 by default and 250 at most.
|
|
295
296
|
|
|
296
297
|
This is not search: it matches no text. Use `dispatch_search` for a keyword or phrase, and
|
|
297
298
|
`dispatch_issues` when you want every issue in a project and its current state.
|
|
298
299
|
|
|
300
|
+
### The owner audit
|
|
301
|
+
|
|
302
|
+
As the owner of a surface, list your area's P0 and P1 issues and staff or close each one nobody
|
|
303
|
+
has started:
|
|
304
|
+
```ts
|
|
305
|
+
dispatch_issues({ project, priority: [0, 1], limit: 250 })
|
|
306
|
+
```
|
|
307
|
+
Every unclaimed row in `triage`, `icebox`, `backlog` or `todo` is a decision: someone takes it and
|
|
308
|
+
builds it, or it closes. A row in `in_progress`, `testing`, `needs_review` or `retro`, or one that
|
|
309
|
+
carries a claim, is work under way ([Issue status is yours to move](#issue-status-is-yours-to-move))
|
|
310
|
+
and is not re-staffed. A todo with a finished spec reads as queued work that nobody is doing
|
|
311
|
+
(LEGION-173 sat in todo for two weeks with a complete spec; AGENTC-1010's v4 plan sat in backlog
|
|
312
|
+
with nobody building it).
|
|
313
|
+
|
|
314
|
+
The audit finds three shapes:
|
|
315
|
+
|
|
316
|
+
- **Unstaffed work.** A plan or measurement exists, and no one is building it.
|
|
317
|
+
- **Unrecorded delivery.** An issue not yet in `testing` or `done`, claimed or not, has a merged PR
|
|
318
|
+
naming it. Check the change live, then move the issue (AGENTC-1033 sat at `triage` after its fix,
|
|
319
|
+
agent-c #20367, merged).
|
|
320
|
+
- **Unrecorded practice.** Someone does the issue's work by hand, more than once, while the issue
|
|
321
|
+
sits in backlog (OPS-132, done by hand on every migration merge). It leaves no plan and no PR to
|
|
322
|
+
find; the tell is your own messages. Doing something by hand more than once means an issue is
|
|
323
|
+
wearing the wrong status.
|
|
324
|
+
|
|
325
|
+
Run the audit as a step of a coordinator's loop, at each checkpoint, not as a habit: these shapes
|
|
326
|
+
are found by running the check, not by noticing them.
|
|
327
|
+
|
|
328
|
+
### Symptom versus cause
|
|
329
|
+
|
|
330
|
+
When a symptom and its cause sit on different issues, the work accrues to the cause's issue, and
|
|
331
|
+
the symptom's issue carries a pointer to it. Before posting a measurement or finding, search
|
|
332
|
+
Dispatch for the failing identity's or component's name, and post on the issue whose title names
|
|
333
|
+
the fix, not the one naming the symptom. A symptom issue gathering messages with no human response
|
|
334
|
+
is the tell. (The production freeze was iterated on AGENTC-546, the failing gate, while its cause
|
|
335
|
+
and answer sat on AGENTC-1010.)
|
|
336
|
+
|
|
299
337
|
## Asking
|
|
300
338
|
|
|
301
339
|
### Before you ask
|