@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 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. 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.",
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.13.0",
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. 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.",
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`, or `updated_since` (an RFC3339
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "5.13.0",
3
+ "version": "5.14.0",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [