@sjawhar/pi-legion-envoy 7.9.3 → 7.10.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
@@ -29659,6 +29659,7 @@ var DEFAULT_ISSUE_PAGE_LIMIT = 50;
29659
29659
  var ASK_TURNS = ["human", "agent"];
29660
29660
  var DELIVERY_CAPABILITIES = ["aside", "btw", "steer"];
29661
29661
  var DELIVERY_DUPLICATE_WINDOW_MS = 72 * 60 * 60 * 1000;
29662
+ var SEARCH_DEGRADED_EMBEDDER_UNAVAILABLE = "embedder_unavailable";
29662
29663
  var DispatchEventSchema = exports_external.object({
29663
29664
  issue_key: exports_external.string().nullable(),
29664
29665
  artifact_id: exports_external.string().nullish(),
@@ -33088,14 +33089,20 @@ function searchAnswer(search, query, offset, configUrl) {
33088
33089
  const lines = results.map((result) => searchResultLine(result, configUrl));
33089
33090
  const noun = count === 1 ? "result" : "results";
33090
33091
  const noResults = `No results for "${query}".`;
33092
+ const degraded = search.degraded === SEARCH_DEGRADED_EMBEDDER_UNAVAILABLE ? "Searched by keyword only: meaning search was unavailable for this request." : undefined;
33091
33093
  if (typeof search.total !== "number") {
33092
33094
  if (offset !== undefined && offset > 0) {
33093
33095
  throw new Error(`Dispatch answered without a total: it predates search paging and ignored offset ${offset}, so this would be its first page again.`);
33094
33096
  }
33095
33097
  return {
33096
- text: count === 0 ? noResults : [`${count} ${noun} for "${query}" (${search.took_ms} ms)`, ...lines].join(`
33098
+ text: count === 0 ? [noResults, ...degraded === undefined ? [] : [degraded]].join(`
33099
+ `) : [
33100
+ `${count} ${noun} for "${query}" (${search.took_ms} ms)`,
33101
+ ...degraded === undefined ? [] : [degraded],
33102
+ ...lines
33103
+ ].join(`
33097
33104
  `),
33098
- details: { query, results }
33105
+ details: { query, results, ...degraded === undefined ? {} : { degraded: search.degraded } }
33099
33106
  };
33100
33107
  }
33101
33108
  const { total, reachable, offset: pageOffset } = search;
@@ -33107,12 +33114,15 @@ function searchAnswer(search, query, offset, configUrl) {
33107
33114
  total,
33108
33115
  reachable,
33109
33116
  offset: pageOffset,
33110
- limit: search.limit
33117
+ limit: search.limit,
33118
+ ...degraded === undefined ? {} : { degraded: search.degraded }
33111
33119
  };
33112
33120
  if (count === 0) {
33113
33121
  return {
33114
- text: total === 0 ? noResults : [
33122
+ text: total === 0 ? [noResults, ...degraded === undefined ? [] : [degraded]].join(`
33123
+ `) : [
33115
33124
  `No results for "${query}" at offset ${pageOffset}: it matches ${total}, and the pages reach the first ${reachable}.`,
33125
+ ...degraded === undefined ? [] : [degraded],
33116
33126
  ...cut === undefined ? [] : [cut]
33117
33127
  ].join(`
33118
33128
  `),
@@ -33123,6 +33133,7 @@ function searchAnswer(search, query, offset, configUrl) {
33123
33133
  return {
33124
33134
  text: [
33125
33135
  `${count} ${noun} for "${query}" (${showing}${search.took_ms} ms)`,
33136
+ ...degraded === undefined ? [] : [degraded],
33126
33137
  ...cut === undefined ? [] : [cut],
33127
33138
  ...lines,
33128
33139
  ...end < reachable ? [`Next page: offset ${end}.`] : []
package/dist/legion.js CHANGED
@@ -13746,6 +13746,7 @@ var DEFAULT_ISSUE_PAGE_LIMIT = 50;
13746
13746
  var ASK_TURNS = ["human", "agent"];
13747
13747
  var DELIVERY_CAPABILITIES = ["aside", "btw", "steer"];
13748
13748
  var DELIVERY_DUPLICATE_WINDOW_MS = 72 * 60 * 60 * 1000;
13749
+ var SEARCH_DEGRADED_EMBEDDER_UNAVAILABLE = "embedder_unavailable";
13749
13750
  var DispatchEventSchema = exports_external.object({
13750
13751
  issue_key: exports_external.string().nullable(),
13751
13752
  artifact_id: exports_external.string().nullish(),
@@ -15843,14 +15844,20 @@ function searchAnswer(search, query, offset, configUrl) {
15843
15844
  const lines = results.map((result) => searchResultLine(result, configUrl));
15844
15845
  const noun = count === 1 ? "result" : "results";
15845
15846
  const noResults = `No results for "${query}".`;
15847
+ const degraded = search.degraded === SEARCH_DEGRADED_EMBEDDER_UNAVAILABLE ? "Searched by keyword only: meaning search was unavailable for this request." : undefined;
15846
15848
  if (typeof search.total !== "number") {
15847
15849
  if (offset !== undefined && offset > 0) {
15848
15850
  throw new Error(`Dispatch answered without a total: it predates search paging and ignored offset ${offset}, so this would be its first page again.`);
15849
15851
  }
15850
15852
  return {
15851
- text: count === 0 ? noResults : [`${count} ${noun} for "${query}" (${search.took_ms} ms)`, ...lines].join(`
15853
+ text: count === 0 ? [noResults, ...degraded === undefined ? [] : [degraded]].join(`
15854
+ `) : [
15855
+ `${count} ${noun} for "${query}" (${search.took_ms} ms)`,
15856
+ ...degraded === undefined ? [] : [degraded],
15857
+ ...lines
15858
+ ].join(`
15852
15859
  `),
15853
- details: { query, results }
15860
+ details: { query, results, ...degraded === undefined ? {} : { degraded: search.degraded } }
15854
15861
  };
15855
15862
  }
15856
15863
  const { total, reachable, offset: pageOffset } = search;
@@ -15862,12 +15869,15 @@ function searchAnswer(search, query, offset, configUrl) {
15862
15869
  total,
15863
15870
  reachable,
15864
15871
  offset: pageOffset,
15865
- limit: search.limit
15872
+ limit: search.limit,
15873
+ ...degraded === undefined ? {} : { degraded: search.degraded }
15866
15874
  };
15867
15875
  if (count === 0) {
15868
15876
  return {
15869
- text: total === 0 ? noResults : [
15877
+ text: total === 0 ? [noResults, ...degraded === undefined ? [] : [degraded]].join(`
15878
+ `) : [
15870
15879
  `No results for "${query}" at offset ${pageOffset}: it matches ${total}, and the pages reach the first ${reachable}.`,
15880
+ ...degraded === undefined ? [] : [degraded],
15871
15881
  ...cut === undefined ? [] : [cut]
15872
15882
  ].join(`
15873
15883
  `),
@@ -15878,6 +15888,7 @@ function searchAnswer(search, query, offset, configUrl) {
15878
15888
  return {
15879
15889
  text: [
15880
15890
  `${count} ${noun} for "${query}" (${showing}${search.took_ms} ms)`,
15891
+ ...degraded === undefined ? [] : [degraded],
15881
15892
  ...cut === undefined ? [] : [cut],
15882
15893
  ...lines,
15883
15894
  ...end < reachable ? [`Next page: offset ${end}.`] : []
@@ -18031,7 +18042,7 @@ function endInjectedUserTurns(sessionID) {
18031
18042
  // package.json
18032
18043
  var package_default = {
18033
18044
  name: "@sjawhar/pi-legion-envoy",
18034
- version: "7.9.3",
18045
+ version: "7.10.1",
18035
18046
  license: "Apache-2.0",
18036
18047
  type: "module",
18037
18048
  omp: {
@@ -164,14 +164,14 @@ do with each hit. What it leaves out:
164
164
  dispatch_search({ query, project?, limit?, offset? })
165
165
  ```
166
166
  Websearch syntax applies: `"merge queue"`, `-daemon`, `OR`. Issues, documents, asks, comments, and messages rank separately; the
167
- merged page orders each kind's best in turn — issue, document, ask, comment, message — and a bare issue key ranks first. A page
168
- holds `limit` hits (20 default, 50 max); the first line gives the total (`showing 1-20 of 312`); see
169
- [Search paging](skill://dispatch/references/issues.md#search-paging) for more. Queries over 1,000 characters are refused: use the
170
- few words `skill://dispatch-first` names, never a pasted passage. Issue hits start with the issue key; document hits start with
171
- `dispatch://PROJECT/artifact/<slug>`, then the link. Cite the hit (`dispatch://KEY` or the doc ref) or say "no prior issue".
172
-
173
- `dispatch_issue` refuses a title that near-duplicates an issue in the same project and returns the candidates (`POSSIBLE_DUPLICATE`).
174
- Read them; reference the existing issue, or repeat the call with `force: true` when it is genuinely new work.
167
+ merged page orders each kind's best in turn — issue, document, ask, comment, message — and a bare issue key ranks first. Each
168
+ kind's list also merges a query embedding's meaning match with keyword hits (LEGION-549): a paraphrase with no shared word can
169
+ still match; without an embedder, it says so and ranks by keyword alone. A page holds `limit` hits (20 default, 50 max); the first
170
+ line gives the total (`showing 1-20 of 312`); see [Search paging](skill://dispatch/references/issues.md#search-paging) for more.
171
+ Queries over 1,000 characters are refused: use the few words `skill://dispatch-first` names, never a pasted passage. Issue hits
172
+ start with the issue key; document hits start with `dispatch://PROJECT/artifact/<slug>`, then the link. Cite the hit (`dispatch://KEY` or the doc ref) or say "no prior issue".
173
+
174
+ `dispatch_issue` refuses a title that near-duplicates an issue in the same project and returns the candidates (`POSSIBLE_DUPLICATE`). Read them; reference the existing issue, or repeat the call with `force: true` when it is genuinely new work.
175
175
  The check compares title words only (shared stemmed terms), never meaning: "four tests that fail a
176
176
  merge" pairs with "four CI gates that cannot fail a merge". So when you force past a candidate, give
177
177
  the new issue a title that names what differs where you can, and open its spec with the
@@ -50,6 +50,11 @@ judgment across many files). Do not name any other agent.
50
50
  | 3. Framework docs | `read` the library's documentation URL | [library] [topic] |
51
51
  | 4. External practices | `web_search`, then `read` the primary source | Current best practices for [topic] |
52
52
 
53
+ Before relying on a step 1 hit, also search for `supersedes: docs/solutions/<its-path>` and
54
+ `Extends docs/solutions/<its-path>` naming it: a newer file may extend or supersede what you
55
+ found, and Legion runs no pass that reconciles these links, so following them is the only way to
56
+ know the hit is still current.
57
+
53
58
  ## Output
54
59
 
55
60
  **Found:** Answer with source (file:line or URL)
@@ -67,13 +67,26 @@ Do not start retro before step 2 or skip it because the change seems mechanical;
67
67
  ## Durable outputs
68
68
 
69
69
  Write the integrated learning as one or more discoverable documents under `docs/solutions/`.
70
- Organize by reusable topic rather than by pull request. Search `docs/solutions/` for the topic
71
- first: when a document already states the rule, update it in place (sharpen the rule, add this
72
- issue and pull request to `related_issues`) rather than writing a sibling; when the new learning
73
- replaces an old document, set the old one's `status: superseded` and add
74
- `superseded_by: docs/solutions/<path>.md`. Open each document with the rule in a few imperative
75
- lines; the incident that taught it goes in an Evidence section below, never in the rule. Each
76
- document uses this front matter:
70
+ Organize by reusable topic rather than by pull request, but never edit a document you did not
71
+ write this retro — not its frontmatter, not its body. Two trees' retros can land within the same
72
+ hour, and an in-place edit (another `related_issues` entry, a sharpened sentence, a `status`
73
+ flip) conflicts with any other tree's edit to the same lines of the same file. Search
74
+ `docs/solutions/` for the topic first; before relying on a hit, also search for
75
+ `supersedes: docs/solutions/<its-path>` and `Extends docs/solutions/<its-path>` naming it —
76
+ Legion runs no pass that reconciles these links, so a newer file that extends or supersedes the
77
+ one you found is discoverable only by following them. Then write a new file of your own, named
78
+ `docs/solutions/<category>/<slug>-<LEGION_ISSUE>.md` so two trees never choose the same path:
79
+
80
+ - **A fresh topic:** state the rule in a few imperative lines; the incident goes in an Evidence
81
+ section below, never in the rule.
82
+ - **A topic an existing document already covers:** underneath its own H1 heading, the first line
83
+ reads `Extends docs/solutions/<existing-path>.md.`; the rule states only the delta.
84
+ - **A topic an existing document states wrongly:** frontmatter adds
85
+ `supersedes: docs/solutions/<existing-path>.md`; the first line under the H1 says why. Leave
86
+ the old file's frontmatter and body untouched: Legion runs no pass that reconciles it, so the
87
+ `supersedes:` link is the only thing that makes the correction discoverable from the old file.
88
+
89
+ Each document uses this front matter:
77
90
 
78
91
  ```yaml
79
92
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "7.9.3",
3
+ "version": "7.10.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {