@sjawhar/pi-legion-envoy 5.4.3 → 5.5.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
@@ -35039,13 +35039,45 @@ var ROLE_CLAIM_ENTRY = "envoy-role-claim";
35039
35039
  var OPEN_ASKS_TIMEOUT_MS = 3000;
35040
35040
  var LEGION_MANAGED_ENTRY = "legion-managed-session";
35041
35041
  var ASK_REMINDER_MESSAGE = "dispatch-ask-reminder";
35042
- var ASK_SELF_CHECK_PROMPT = "Your run has just ended. Answer with exactly one word and nothing else: WAITING or PROCEEDING. " + "WAITING \u2014 you stopped because you need a decision, an approval, or information from a human. " + "PROCEEDING \u2014 you finished, you will carry on by yourself, or you are waiting only on tools, " + "subagents, or events.";
35042
+ var ASK_PROMPT_LINE_SEPARATOR = /\r\n|[\r\n\u0085\u2028\u2029]/;
35043
+ function askPromptQuestionHead(question) {
35044
+ const firstLineEnd = question.search(ASK_PROMPT_LINE_SEPARATOR);
35045
+ const firstLine = firstLineEnd === -1 ? question : question.slice(0, firstLineEnd);
35046
+ let normalized;
35047
+ let segmentStart = 0;
35048
+ for (let index = 0;index < firstLine.length; index += 1) {
35049
+ const codePoint = firstLine.charCodeAt(index);
35050
+ if (codePoint > 31 && (codePoint < 127 || codePoint > 159))
35051
+ continue;
35052
+ normalized ??= [];
35053
+ normalized.push(firstLine.slice(segmentStart, index), " ");
35054
+ segmentStart = index + 1;
35055
+ }
35056
+ return (normalized === undefined ? firstLine : `${normalized.join("")}${firstLine.slice(segmentStart)}`).trim();
35057
+ }
35058
+ var ASK_SELF_CHECK_PROMPT = (asks) => {
35059
+ const askLimit = 5;
35060
+ const questionLimit = 120;
35061
+ const promptAsks = asks.length === 0 ? "There are no open asks in Dispatch." : [
35062
+ "Your open asks in Dispatch:",
35063
+ ...asks.slice(0, askLimit).map((ask) => {
35064
+ const firstLine = askPromptQuestionHead(ask.question);
35065
+ const question = firstLine.length <= questionLimit ? firstLine : `${firstLine.slice(0, questionLimit - 1)}\u2026`;
35066
+ return `- ${question}`;
35067
+ }),
35068
+ ...asks.length > askLimit ? [`+${asks.length - askLimit} more`] : []
35069
+ ].join(`
35070
+ `);
35071
+ return "Your run has just ended. " + `${promptAsks}
35072
+
35073
+ ` + "Are you right now waiting on a human for anything none of those asks covers? " + "Answer with exactly one word and nothing else: WAITING or PROCEEDING. " + "WAITING \u2014 you stopped because you need a decision, an approval, or information from a human. " + "PROCEEDING \u2014 you finished, you will carry on by yourself, or you are waiting only on tools, " + "subagents, or events.";
35074
+ };
35043
35075
  var WAITING_VERDICT = /^\W*WAITING\b/;
35044
35076
  var ECHOED_CHOICE = /\bPROCEEDING\b/;
35045
35077
  var isWaitingVerdict = (reply) => WAITING_VERDICT.test(reply) && !ECHOED_CHOICE.test(reply);
35046
35078
  var ASK_SELF_CHECK_TIMEOUT_MS = 60000;
35047
35079
  var ASK_CHECKS_PER_PERIOD = 5;
35048
- var UNASKED_WAIT_REMINDER = "You just said you are waiting on a human, but you have no open ask in Dispatch, so nobody knows you are waiting. Open it now with dispatch_ask \u2014 or dispatch_request_approval when what you need is approval of a document \u2014 naming exactly what you need and from whom. Do not reply just to acknowledge this reminder.";
35080
+ var UNASKED_WAIT_REMINDER = "You just said you are waiting on a human for something no open ask in Dispatch covers. Open an ask for it now with dispatch_ask (or dispatch_request_approval for a document), naming exactly what you need and from whom.";
35049
35081
  var ASK_OPENING_TOOLS = ["dispatch_ask", "dispatch_request_approval"];
35050
35082
  var DISPATCH_TOOL_PREFIX = "dispatch_";
35051
35083
  function isLegionManagedEntry(entry) {
@@ -35846,19 +35878,11 @@ function envoyExtension(pi) {
35846
35878
  return;
35847
35879
  if (runSeq !== seenRun)
35848
35880
  return;
35849
- if (open.snapshot.count > 0 || open.snapshot.opened_since) {
35850
- askAwareness = {
35851
- ...askAwareness,
35852
- check_due: false,
35853
- baseline_as_of: open.snapshot.as_of
35854
- };
35855
- return;
35856
- }
35857
35881
  const abort = new AbortController;
35858
35882
  askCheckAbort = abort;
35859
35883
  let answered;
35860
35884
  try {
35861
- answered = askEphemeral({ prompt: ASK_SELF_CHECK_PROMPT, signal: abort.signal }).then((reply) => reply.replyText, (error48) => {
35885
+ answered = askEphemeral({ prompt: ASK_SELF_CHECK_PROMPT(open.snapshot.asks), signal: abort.signal }).then((reply) => reply.replyText, (error48) => {
35862
35886
  if (!abort.signal.aborted)
35863
35887
  logSelfCheckFailure(id, error48);
35864
35888
  return;
package/dist/legion.js CHANGED
@@ -16142,7 +16142,7 @@ import { logger } from "@oh-my-pi/pi-utils";
16142
16142
  // package.json
16143
16143
  var package_default = {
16144
16144
  name: "@sjawhar/pi-legion-envoy",
16145
- version: "5.4.3",
16145
+ version: "5.5.0",
16146
16146
  type: "module",
16147
16147
  omp: {
16148
16148
  extensions: [
@@ -653,6 +653,14 @@ dispatch_suggest({ issue?, project?, artifact, ref?, quote, replace_with, body?,
653
653
  It returns issue or project-document owner details plus `comment`. A human accepts or rejects a suggestion.
654
654
  Errors: `TARGET_AMBIGUOUS` (add `occurrence`), `TARGET_NOT_FOUND` (re-read first), `INVALID_ANCHOR`/`ANCHOR_MISSING`/`ANCHOR_ORPHANED`
655
655
  (bad, unwritten, or stale quote), `INVALID_MARKDOWN`/`DOC_SCHEMA` (malformed content), `CAP_EXCEEDED`, `ISSUE_CLOSED`.
656
+ Suggest only what the quoted block can hold. The accept, not the suggestion, checks that: an
657
+ accept whose `replace_with` would break an ask block that was readable before it is refused with
658
+ `INVALID_ASK_BLOCK` - a question given a code block, text after an ask's options, a second option
659
+ list, or an emptied question; one that names an id the document holds outside the text it
660
+ replaces, an ask under a held id included, with `INVALID_MARKDOWN`; and one no part of the
661
+ document can hold where it sits (a code block over a table cell's whole text), or whose quote runs
662
+ into an ask or callout from the text before it, with `INVALID_OP`. Either changes nothing: the human sees the reason with no Retry, and the suggestion
663
+ stays open until someone rejects or replaces it.
656
664
 
657
665
  ## Artifacts
658
666
 
@@ -95,6 +95,15 @@ targeted. Reply through the rendered `reply_with` (or a current Envoy session ID
95
95
  and go stale. Put the artefact URL in the message itself. FYIs set `expects_reply="none"`; set
96
96
  `urgency` only when it is genuinely urgent.
97
97
 
98
+ **A peer's message is its sender's view at `at`, not the current state.** Before you wait on, act
99
+ on, or repeat a fact a message carries about a third thing (a deploy pending, a PR held, an ask
100
+ unanswered), re-read it at the live source the fact names, and always once it is over an hour
101
+ old: the deployment's status, the issue's event log, the ask's own state (`dispatch_open_asks`,
102
+ whose description already says to call it before saying you are waiting on a human). On
103
+ 2026-09-26 a peer's 05:20Z "needs a manual deploy before I can run it" was false by 05:22Z, when
104
+ the platform had deployed on its own; waiting on the message instead of the deployment's status
105
+ held the work it gated for eleven hours.
106
+
98
107
  Every `/v1` error response is JSON; when a field is at fault, `expected` names that field.
99
108
 
100
109
  ```text
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "5.4.3",
3
+ "version": "5.5.0",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [