@sjawhar/opencode-legion-envoy 1.20.0 → 1.20.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.
@@ -13786,7 +13786,7 @@ var dispatchToolSpecs = [
13786
13786
  issue: z.string().describe(ISSUE_REFERENCE).optional(),
13787
13787
  project: z.string().describe("Project key owning the document.").optional(),
13788
13788
  artifact: z.string().describe("Project document artifact id, slug, or filename.").optional(),
13789
- ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
13789
+ ref: z.string().describe("Optional dispatch:// reference (issue, document, message, or ask); appended to the question and rendered as a link.").optional(),
13790
13790
  question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
13791
13791
  kind: z.enum(["action"]).describe("Optional human to-do ask kind.").optional(),
13792
13792
  options: z.array(z.object({
@@ -15035,6 +15035,19 @@ function askKind(args) {
15035
15035
  return value;
15036
15036
  throw new Error("kind must be action");
15037
15037
  }
15038
+ function askQuestionWithRef(args) {
15039
+ const question = stringArg(args, "question");
15040
+ const ref = optionalString(args, "ref");
15041
+ if (ref === undefined || question.includes(ref))
15042
+ return question;
15043
+ const withRef = `${question}
15044
+
15045
+ Ref: ${ref}`;
15046
+ if (withRef.length > 800) {
15047
+ throw new Error("question plus ref must be at most 800 characters");
15048
+ }
15049
+ return withRef;
15050
+ }
15038
15051
  function parseDispatchRef(ref) {
15039
15052
  const projectDocument = ref.match(/^dispatch:\/\/([A-Z][A-Z0-9]{1,9})\/artifact\/([^/@]+)(?:@v(\d+))?(?:\/(ask|comment)\/([^/]+))?$/);
15040
15053
  if (projectDocument) {
@@ -15117,6 +15130,9 @@ async function resolveOwnerArguments(tool, args, cwd, env, exec) {
15117
15130
  if (issueFreeTools[tool] === true)
15118
15131
  return { args, ref: null, owner: null };
15119
15132
  const refArgument = args.ref;
15133
+ if (tool === "dispatch_ask" && typeof refArgument === "string" && !refArgument.startsWith("dispatch://")) {
15134
+ throw new Error("ref must be a dispatch:// reference");
15135
+ }
15120
15136
  const ref = typeof refArgument === "string" ? parseDispatchRef(refArgument) ?? (() => {
15121
15137
  throw new Error("ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, or " + "dispatch://PROJECT/artifact/<document-ref> (an artifact id, slug, or filename)");
15122
15138
  })() : null;
@@ -15526,7 +15542,7 @@ async function executeDispatchTool(input) {
15526
15542
  const kind = askKind(args);
15527
15543
  const anchored = anchorArgs && resolved ? anchor(resolved.artifact, anchorArgs) : undefined;
15528
15544
  const askInput = {
15529
- question: stringArg(args, "question"),
15545
+ question: askQuestionWithRef(args),
15530
15546
  ...kind === undefined ? {} : { kind },
15531
15547
  ...Array.isArray(options) ? { options } : {},
15532
15548
  ...multiple === undefined ? {} : { multiple },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "1.20.0",
3
+ "version": "1.20.1",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -111,6 +111,7 @@ dispatch_ask({
111
111
  issue?,
112
112
  project?,
113
113
  artifact?,
114
+ ref?,
114
115
  question,
115
116
  options?: { label, description? }[],
116
117
  multiple?,
@@ -120,6 +121,8 @@ dispatch_ask({
120
121
  ```
121
122
  It returns `details` `{ issue, topic, ask }` for an issue or `{ project, artifact, document, topic, ask }` for a project document.
122
123
 
124
+ References belong in the question text; `ref` is sugar that appends its `dispatch://` value to the question as a rendered link.
125
+
123
126
  An ask is read on a phone by someone who has not read the code. Open with one or two plain
124
127
  sentences: what needs deciding and why it matters now. Each option is a button with a label and
125
128
  one sentence saying what happens if it is chosen; never enumerate choices in prose. Put the
@@ -341,6 +344,24 @@ with your text. Never do that: the spec is edited in place with `dispatch_doc_ed
341
344
  artifact by the slug shown in the upload result or by its filename, and a project document by its artifact id, slug, or filename; the
342
345
  slug also arrives on `artifact.created` events.
343
346
 
347
+ ## Structure over stream
348
+
349
+ Dispatch is a structured workspace, never a message stream (Sami, 2026-09-13, verbatim: "strange
350
+ to me that agents keep trying to use dispatch as a giant stream of messages instead of
351
+ high-signal, structured conversation"). The structure IS the product:
352
+
353
+ - **One issue per piece of work.** A new deliverable — an email to send, a document to review, a
354
+ decision with its own lifecycle — gets its own issue with the content as the issue's document
355
+ (spec artifact), not a message pile on an existing issue. If you are about to post a message
356
+ carrying a draft, a spec, or anything over a couple of paragraphs, stop: that is an issue with a
357
+ document, or an artifact on the issue it belongs to.
358
+ - **Content lives in documents; decisions live in asks; messages only announce.** A draft the
359
+ human must read goes in a document artifact the dashboard renders with versions and margins; the
360
+ ask that needs their word references it (`ref`, or the `dispatch://` link inline) instead of
361
+ restating it. A message never carries a body a human has to scroll.
362
+ - **Never split one deliverable across a message + an ask that points at it.** Ask the question
363
+ with the document reference in the question text; the reader lands on the content in one click.
364
+
344
365
  ## Messages
345
366
 
346
367
  Dispatch is a high-signal record for humans, not a log of what you are doing. A message is a reply to a human's message, or a