@sjawhar/pi-legion-envoy 7.6.5 → 7.7.1

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
@@ -32756,6 +32756,32 @@ function renderAdvice(tool, key, advice, opts) {
32756
32756
  }
32757
32757
  return lines;
32758
32758
  }
32759
+ function renderSuggestions(suggestions, configUrl) {
32760
+ if (suggestions === undefined)
32761
+ return [];
32762
+ if (suggestions.missing !== undefined) {
32763
+ return [`Related-item search was skipped: ${suggestions.missing}.`];
32764
+ }
32765
+ const lines = [];
32766
+ if (suggestions.related.length > 0) {
32767
+ lines.push("Possibly related, found by search:");
32768
+ for (const item of suggestions.related) {
32769
+ lines.push(`- ${suggestionLabel(item)} \u2192 ${new URL(item.href, configUrl).toString()}`);
32770
+ }
32771
+ }
32772
+ if (suggestions.decision !== undefined) {
32773
+ const item = suggestions.decision;
32774
+ const when = item.answered_at === undefined ? "" : ` on ${item.answered_at}`;
32775
+ lines.push(`A past decision may already answer this: ${suggestionLabel(item)}, answered by ${item.answered_by}${when} \u2192 ${new URL(item.href, configUrl).toString()}`);
32776
+ }
32777
+ return lines;
32778
+ }
32779
+ function suggestionLabel(item) {
32780
+ if (item.owner.kind === "issue") {
32781
+ return `${item.owner.key} [${item.owner.status}] ${item.owner.title}`;
32782
+ }
32783
+ return `${item.owner.name} (${item.owner.project}/${item.owner.slug})`;
32784
+ }
32759
32785
  function documentResultDetails(artifact) {
32760
32786
  return {
32761
32787
  project: artifact.project,
@@ -33936,7 +33962,8 @@ async function executeDispatchTool(input) {
33936
33962
  ...renderAdvice(input.tool, created.key, created.advice, {
33937
33963
  isPrimarySpec: spec !== undefined
33938
33964
  }),
33939
- ...componentGuidance === undefined ? [] : [componentGuidance]
33965
+ ...componentGuidance === undefined ? [] : [componentGuidance],
33966
+ ...renderSuggestions(created.advice?.suggestions, configUrl)
33940
33967
  ];
33941
33968
  return {
33942
33969
  text: [
@@ -34216,7 +34243,10 @@ async function executeDispatchTool(input) {
34216
34243
  };
34217
34244
  const ask = resolved?.owner.kind === "project" ? await client.artifactAsk(resolved.artifact.id, askInput) : await client.ask(issue2(), askInput);
34218
34245
  const askOwner = ask.issue_key !== null ? issueTopic(ask.issue_key) : resolved === undefined ? issueTopic(issue2()) : documentTopic(resolved.artifact);
34219
- const adviceLines = renderAdvice(input.tool, askOwner.label, ask.advice, {});
34246
+ const adviceLines = [
34247
+ ...renderAdvice(input.tool, askOwner.label, ask.advice, {}),
34248
+ ...renderSuggestions(ask.advice?.suggestions, configUrl)
34249
+ ];
34220
34250
  return {
34221
34251
  text: [
34222
34252
  `Asked ${ask.id} on ${askOwner.label} (urgency ${ask.urgency}): ${ask.question}
package/dist/legion.js CHANGED
@@ -15541,6 +15541,32 @@ function renderAdvice(tool, key, advice, opts) {
15541
15541
  }
15542
15542
  return lines;
15543
15543
  }
15544
+ function renderSuggestions(suggestions, configUrl) {
15545
+ if (suggestions === undefined)
15546
+ return [];
15547
+ if (suggestions.missing !== undefined) {
15548
+ return [`Related-item search was skipped: ${suggestions.missing}.`];
15549
+ }
15550
+ const lines = [];
15551
+ if (suggestions.related.length > 0) {
15552
+ lines.push("Possibly related, found by search:");
15553
+ for (const item of suggestions.related) {
15554
+ lines.push(`- ${suggestionLabel(item)} \u2192 ${new URL(item.href, configUrl).toString()}`);
15555
+ }
15556
+ }
15557
+ if (suggestions.decision !== undefined) {
15558
+ const item = suggestions.decision;
15559
+ const when = item.answered_at === undefined ? "" : ` on ${item.answered_at}`;
15560
+ lines.push(`A past decision may already answer this: ${suggestionLabel(item)}, answered by ${item.answered_by}${when} \u2192 ${new URL(item.href, configUrl).toString()}`);
15561
+ }
15562
+ return lines;
15563
+ }
15564
+ function suggestionLabel(item) {
15565
+ if (item.owner.kind === "issue") {
15566
+ return `${item.owner.key} [${item.owner.status}] ${item.owner.title}`;
15567
+ }
15568
+ return `${item.owner.name} (${item.owner.project}/${item.owner.slug})`;
15569
+ }
15544
15570
  function documentResultDetails(artifact) {
15545
15571
  return {
15546
15572
  project: artifact.project,
@@ -16721,7 +16747,8 @@ async function executeDispatchTool(input) {
16721
16747
  ...renderAdvice(input.tool, created.key, created.advice, {
16722
16748
  isPrimarySpec: spec !== undefined
16723
16749
  }),
16724
- ...componentGuidance === undefined ? [] : [componentGuidance]
16750
+ ...componentGuidance === undefined ? [] : [componentGuidance],
16751
+ ...renderSuggestions(created.advice?.suggestions, configUrl)
16725
16752
  ];
16726
16753
  return {
16727
16754
  text: [
@@ -17001,7 +17028,10 @@ async function executeDispatchTool(input) {
17001
17028
  };
17002
17029
  const ask = resolved?.owner.kind === "project" ? await client.artifactAsk(resolved.artifact.id, askInput) : await client.ask(issue2(), askInput);
17003
17030
  const askOwner = ask.issue_key !== null ? issueTopic(ask.issue_key) : resolved === undefined ? issueTopic(issue2()) : documentTopic(resolved.artifact);
17004
- const adviceLines = renderAdvice(input.tool, askOwner.label, ask.advice, {});
17031
+ const adviceLines = [
17032
+ ...renderAdvice(input.tool, askOwner.label, ask.advice, {}),
17033
+ ...renderSuggestions(ask.advice?.suggestions, configUrl)
17034
+ ];
17005
17035
  return {
17006
17036
  text: [
17007
17037
  `Asked ${ask.id} on ${askOwner.label} (urgency ${ask.urgency}): ${ask.question}
@@ -17524,7 +17554,7 @@ function endInjectedUserTurns(sessionID) {
17524
17554
  // package.json
17525
17555
  var package_default = {
17526
17556
  name: "@sjawhar/pi-legion-envoy",
17527
- version: "7.6.5",
17557
+ version: "7.7.1",
17528
17558
  license: "Apache-2.0",
17529
17559
  type: "module",
17530
17560
  omp: {
@@ -18460,7 +18490,7 @@ function handoffSchemaFields(z2) {
18460
18490
  ready: z2.boolean().optional()
18461
18491
  };
18462
18492
  }
18463
- var HANDOFF_DESCRIPTION = "Handoff actions (phase workers; the daemon accepts a completion only from the role working " + "the issue's current phase, never from an architect): handoff_write writes this phase's handoff " + "(`phase`, and `data`: the phase-specific fields as a JSON object, never the schemaVersion, " + "phase and completed the command writes itself) to `.legion/<phase>.json` in " + "the issue workspace; handoff_read returns the handoffs (every phase, or `phase`); " + "handoff_complete reports this phase complete to the daemon (`summary`: two sentences for the " + "architect, or the merger's READY packet; `verdict` pass|fail when your role's instructions " + "require one; `ready: true` for the merger's READY; no `phase` is needed, and one other than " + "your own is refused). Each " + "returns the command's output; a failed action changed nothing. What a later phase needs goes " + "in your handoff; a question for another live role goes to its role topic with envoy_publish.";
18493
+ var HANDOFF_DESCRIPTION = "Handoff actions (phase workers; the daemon accepts a completion only from the role working " + "the issue's current phase, never from an architect): handoff_write writes this phase's handoff " + "(`phase`, and `data`: the phase-specific fields as a JSON object, never the schemaVersion, " + "phase, completed and issue the command writes itself) to `.legion/<phase>.json` in " + "the issue workspace; handoff_read returns the handoffs (every phase, or `phase`); " + "handoff_complete reports this phase complete to the daemon (`summary`: two sentences for the " + "architect, or the merger's READY packet; `verdict` pass|fail when your role's instructions " + "require one; `ready: true` for the merger's READY; no `phase` is needed, and one other than " + "your own is refused). Each " + "returns the command's output; a failed action changed nothing. What a later phase needs goes " + "in your handoff; a question for another live role goes to its role topic with envoy_publish.";
18464
18494
  function rootArchitectHandoffRefusal(operation) {
18465
18495
  return `${operation} is not available to a root architect session; a root architect reads handoffs with \`legion handoff read [--phase <phase>]\` from bash`;
18466
18496
  }
@@ -27,6 +27,10 @@ parent's children and the issue's `Components:` line show where the rest of that
27
27
 
28
28
  ## What to do with what you find
29
29
 
30
+ Filing an issue or opening an ask also searches for you: the result's `advice.suggestions` names
31
+ likely duplicates or a decision that may already settle it. Treat a hit there the same as one you
32
+ found yourself.
33
+
30
34
  - **The work is already tracked: extend that issue.** Put the finding on it (a comment, a message,
31
35
  or an edit to its spec) instead of filing another. File a new issue only when no hit covers the
32
36
  work, and cite the nearest one you ruled out (`dispatch://KEY`).
@@ -250,8 +250,10 @@ The daemon keeps this order from its fixed table; you start none of its steps:
250
250
 
251
251
  1. tester green and review cycles complete;
252
252
  2. on a clean review, the reviewer approves the head by SHA, and the daemon moves the issue to
253
- `retro`. No role pushes a `.legion/` deletion: the approved head still carries `.legion/`, and
254
- the operator removes it from the default branch in a follow-up pull request after the merge;
253
+ `retro`. No role pushes a `.legion/` deletion: the approved head still carries `.legion/`. The
254
+ daemon strips whatever `.legion/` main still carries from the next issue's branch before any of
255
+ its roles start, so that tree's own merge carries the removal onto the default branch; no
256
+ operator sweep follows;
255
257
  3. retro commits its learnings under `docs/solutions/` on top of the approved head; that
256
258
  commit does not void the approval and never returns the tree to the tester or reviewer;
257
259
  4. the merger verifies the current head is the reviewer-approved head plus only commits that
@@ -19,7 +19,9 @@ retrospective's durable output.
19
19
 
20
20
  1. Tester green and all code-review cycles finish.
21
21
  2. The reviewer approves the head. It still carries `.legion/`: no role removes it before the
22
- merge, and the operator removes it from the default branch after the merge.
22
+ merge. The daemon strips whatever `.legion/` main still carries from the next issue's branch
23
+ before any of its roles start, so that tree's own merge carries the removal onto the default
24
+ branch; no operator sweep follows.
23
25
  3. Run this retro: commit durable learnings to `docs/solutions/` and post the retro message on
24
26
  the Dispatch issue.
25
27
  Retro writes **no `.legion` file**, so it never changes the approved head's handoffs.
@@ -397,9 +397,11 @@ pushes nothing.
397
397
 
398
398
  Do not report phase completion until the write, existence check, handoff commit, and push
399
399
  succeed. This is the committed copy the next phase reads after revival. No phase removes
400
- `.legion/`: the reviewer approves a head that carries it, and the operator removes it from the
401
- default branch after the merge. Retro and the post-merge production check write no
402
- `.legion/<phase>.json`, commit no handoff, and report with `handoff_complete` alone (below).
400
+ `.legion/`: the reviewer approves a head that carries it. The daemon strips any `.legion/` still on
401
+ main from the next issue's branch before any of its roles start (dispatch://LEGION-565), so that
402
+ tree's own merge carries the removal onto the default branch; no operator sweep follows. Retro and
403
+ the post-merge production check write no `.legion/<phase>.json`, commit no handoff, and report with
404
+ `handoff_complete` alone (below).
403
405
 
404
406
  ## Completion: report to the architect, then stay
405
407
 
@@ -6,11 +6,13 @@ path it cites is in sjawhar/legion.
6
6
 
7
7
  The order, in full: the tester's evidence green → the reviewer's approval of the head →
8
8
  retro → the merger's READY → the human merge → the implementer's production check. No role
9
- removes `.legion/` before the merge: the approved head carries it, and the operator removes it
10
- from the default branch after the merge. After the approval, only retro's `docs/solutions/`
11
- commit leaves it standing on its own (*Retro*, below). A conflict-forced merge goes back to the
12
- reviewer for a confirmation or a new round, as the fingerprint decides (*The reviewer*, below,
13
- and `skill://legion-worker/references/conflicts-and-rewrites.md`), and any other change voids it.
9
+ removes `.legion/` before the merge: the approved head carries it. The daemon strips whatever
10
+ `.legion/` main still carries from the next issue's branch before any of its roles start
11
+ (dispatch://LEGION-565), so that tree's own merge carries the removal onto the default branch; no
12
+ operator sweep follows. After the approval, only retro's `docs/solutions/` commit leaves it
13
+ standing on its own (*Retro*, below). A conflict-forced merge goes back to the reviewer for a
14
+ confirmation or a new round, as the fingerprint decides (*The reviewer*, below, and
15
+ `skill://legion-worker/references/conflicts-and-rewrites.md`), and any other change voids it.
14
16
 
15
17
  ## The reviewer
16
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "7.6.5",
3
+ "version": "7.7.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {