@sjawhar/opencode-legion-envoy 6.1.0 → 6.3.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.
@@ -13605,6 +13605,12 @@ var askEventPayloadFields = {
13605
13605
  question: exports_external.string().optional(),
13606
13606
  options: exports_external.array(exports_external.object({ label: exports_external.string().optional() })).optional(),
13607
13607
  answer: exports_external.object({ selected: exports_external.array(exports_external.string()).nullish(), text: exports_external.string().nullish() }).nullish(),
13608
+ previous_answer: exports_external.object({
13609
+ user: exports_external.string().optional(),
13610
+ selected: exports_external.array(exports_external.string()).nullish(),
13611
+ text: exports_external.string().nullish(),
13612
+ at: exports_external.string().optional()
13613
+ }).nullish(),
13608
13614
  anchor: exports_external.object({
13609
13615
  quote: exports_external.string().optional(),
13610
13616
  mark_id: exports_external.string().optional(),
@@ -16595,8 +16601,10 @@ function eventHead(event) {
16595
16601
  case "ask.handed_back":
16596
16602
  case "ask.resolved":
16597
16603
  return textHead(event.payload.question);
16598
- case "ask.answered":
16599
- return `${textHead(event.payload.question)} -> ${textHead(askAnswerText(event.payload.answer))}`;
16604
+ case "ask.answered": {
16605
+ const previousAnswer = event.payload.previous_answer;
16606
+ return `${textHead(event.payload.question)} -> ${textHead(askAnswerText(event.payload.answer))}${previousAnswer === undefined ? "" : ` (was: ${textHead(askAnswerText(previousAnswer))})`}`;
16607
+ }
16600
16608
  case "comment.created":
16601
16609
  case "comment.answered":
16602
16610
  case "comment.anchor_refreshed":
@@ -16637,8 +16645,9 @@ function childrenSummary(issue2) {
16637
16645
  ].join(`
16638
16646
  `);
16639
16647
  }
16640
- function askSummary({ ask, replies }, graph) {
16648
+ function askSummary({ ask, replies, answers }, graph) {
16641
16649
  const answer = ask.answer;
16650
+ const earlierAnswers = answers.slice(0, -1);
16642
16651
  const chain = replies.flatMap((reply) => [
16643
16652
  `${reply.id} \xB7 ${actorText(reply.author)}`,
16644
16653
  `Body: ${reply.body}`
@@ -16655,6 +16664,10 @@ function askSummary({ ask, replies }, graph) {
16655
16664
  `- Selected: ${answer.selected.length === 0 ? "none" : answer.selected.join(", ")}`,
16656
16665
  ...answer.text === null ? [] : [`- Text: ${answer.text}`]
16657
16666
  ],
16667
+ ...earlierAnswers.length === 0 ? [] : [
16668
+ "Earlier answers:",
16669
+ ...earlierAnswers.map((earlier) => `- ${earlier.at} \xB7 ${earlier.user} \xB7 ${askAnswerText(earlier)}`)
16670
+ ],
16658
16671
  ...ask.resolution === undefined ? [] : [
16659
16672
  "Resolution:",
16660
16673
  `- By: ${ask.resolution.actor.id}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "6.1.0",
3
+ "version": "6.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/src/server.js",
@@ -338,7 +338,7 @@ permission you already hold, an API that replaces the click. One ask per item, `
338
338
  when work is stopped on it; while it is open, keep working on everything that is not.
339
339
 
340
340
  Once an ask is open (who answers it, handing a human a to-do, editing, retracting or resolving it,
341
- answering a clarification, whose turn a reply gives), see
341
+ answering a clarification, whose turn a reply gives, an answer the human changes), see
342
342
  [Asks after they open](skill://dispatch/references/asks.md).
343
343
 
344
344
  ## Architecture components
@@ -45,6 +45,9 @@ dispatch_edit_ask({
45
45
  At least one field besides `ask` is required. Use this only while the same decision remains open: it keeps the prior text in the event
46
46
  log and invalidates any answer draft against the prior `edited_at` revision, so the human sees the new wording and explicitly reconfirms.
47
47
  An answered or resolved ask cannot be edited. If the decision is moot or superseded, retract the old ask and open a new one.
48
+ A human can change an answer they gave. The change arrives as another `ask.answered` frame whose
49
+ `previous_answer` names the answer it replaced, through the same route the first answer took, and
50
+ `dispatch_read` of the ask lists every earlier answer. Act on the newest answer.
48
51
 
49
52
  An ask that lives as an `ask` block in a document keeps its question and options in the block, and `dispatch_edit_ask` writes the
50
53
  block along with the row, so the edit stands and the document reads the same. It changes only the fields you name: pass `urgency`
@@ -197,6 +197,6 @@ an existing paragraph is the question that should become a decision.
197
197
 
198
198
  An ask block has two ids: the block id, shown as `:::ask{#<id> …}` in the rendered document and
199
199
  taken bare by `move`/`delete` in `block` (the `block:<id>` form is only for `before`/`after`
200
- anchors), and the ask id, which `dispatch_open_asks`, the dashboard's `?ask=` link, `dispatch_read`
201
- and `dispatch_comment({ reply_to_ask })` use. They differ; `dispatch://KEY/ask/<block-id>` answers
202
- `not found`.
200
+ anchors), and the ask id, which `dispatch_open_asks`, the dashboard's ask links (`/asks/<id>`,
201
+ `?ask=`), `dispatch_read` and `dispatch_comment({ reply_to_ask })` use. They differ;
202
+ `dispatch://KEY/ask/<block-id>` answers `not found`.
@@ -230,9 +230,10 @@ review and the merge-gate sequence by the daemon's table.
230
230
 
231
231
  Retro is mandatory for every issue that passed review, before merge, and the daemon runs it: when
232
232
  the reviewer's approval ends the review round, it moves the issue to `retro` and starts the
233
- implementer on it, resuming the same agent from its session (a worker is suspended when its phase
234
- ends, never after an idle window). You start nothing for it. Never `envoy_publish` to a finished
235
- worker's role topic to start retro: a suspended role is not running to receive it.
233
+ implementer on it, in the same agent's session, which stayed live after its phase ended (every
234
+ started role stays live until its issue closes). You start nothing for it. Never `envoy_publish` to
235
+ the implementer's role topic to start retro: the daemon's start is what records which role owns
236
+ the task.
236
237
 
237
238
  Wait for the implementer to report its durable retro result. Retro output is
238
239
  `docs/solutions/`, the PR body content the repository's instructions derive from the pull
@@ -68,10 +68,10 @@ into a spec yourself: the architect decides whether the human must answer it and
68
68
  since a new version of an approved root spec closes the tree's design gate. A standalone to-do
69
69
  only a human can do is a `dispatch_ask`, and its replies return to your own session.
70
70
 
71
- Because the same agent is always resumed for its phase, you may receive more than one
72
- assignment across your lifetime: once the daemon ends your phase it suspends you, and when a later
73
- event (a review round, a red check) starts your role again it resumes this same session with a new
74
- prompt. Treat it as a continuation — re-read the current issue and your own prior handoff, since
71
+ Because the same agent works its role until the issue closes, you may receive more than one
72
+ assignment across your lifetime: your session stays live after your phase ends, and when a later
73
+ event (a review round, a red check) starts your role again the new prompt arrives in this same
74
+ session. Treat it as a continuation — re-read the current issue and your own prior handoff, since
75
75
  time has passed — never as a fresh identity.
76
76
 
77
77
  ## Deployment instructions
@@ -93,9 +93,9 @@ implementer's production check after the merge
93
93
  Reach any live role on this issue the same way you reach the architect: `envoy_publish` to
94
94
  `notifications.role.` followed by that role's encoded token. Use it when you need context an
95
95
  earlier phase has that its handoff doesn't cover — ask the planner why a constraint was
96
- scoped that way, ask the implementer what a commit actually did. The daemon suspends a role when
97
- its phase ends, so a role that finished is not running to answer you: read its committed handoff
98
- instead.
96
+ scoped that way, ask the implementer what a commit actually did. A role that finished its phase
97
+ stays live and answers until its issue leaves the workflow. If a publish is rejected with 404,
98
+ read that role's committed handoff.
99
99
 
100
100
  ## Workspace and handoff precedence
101
101
 
@@ -111,10 +111,14 @@ Never rely on the inherited cwd. Every later repository shell command **MUST** b
111
111
  native filesystem tool paths **MUST** be absolute under that workspace. Do not create an
112
112
  isolated worktree, change the workspace topology, or mix another issue's work into it.
113
113
  Concurrent issues have disjoint workspaces; only the currently active phase mutates this
114
- one. After you complete, treat `$LEGION_WORKSPACE` as read-only: a finished role is not running to
115
- answer questions or to keep editing. Do not create new commits, run
116
- `jj -R "$LEGION_WORKSPACE" new`, or touch tracked files once your own handoff is committed
117
- (and, for the implementer, pushed) — a code change belongs to whichever phase is active now.
114
+ one. After you complete and go idle, treat `$LEGION_WORKSPACE` as read-only in every later
115
+ turn, including one an Envoy question starts: you are kept alive to answer questions, not to keep
116
+ editing. Do not create new commits, run `jj -R "$LEGION_WORKSPACE" new`, or touch tracked files
117
+ once your own handoff is committed (and, for the implementer, pushed) — a code change belongs to
118
+ whichever phase is active now. The same holds once the Go daemon has taken your phase back without
119
+ your completion: CI settling red while you tested, or reviewed a round you had not completed,
120
+ moves the issue to `implementing` and interrupts your turn, and the implementer starts only once
121
+ that turn has ended. Do not resume the interrupted work afterward.
118
122
 
119
123
  On every start, and especially after revival or re-creation, read the issue and then the
120
124
  committed predecessor handoffs in lifecycle order from
@@ -463,13 +467,18 @@ do:
463
467
  Quote the answer verbatim in what you tell the architect: with the run and phase it names, the
464
468
  difference between "my work is lost" and "my work belongs to the previous run" is visible.
465
469
 
466
- **Stay in this session afterward.** Your process does not exit on its own when your phase
467
- completes: the daemon suspends it when it ends your phase, at the end of your turn, so a finished
468
- role is not running to answer questions. When the daemon starts your role again it resumes this
469
- same session from its session file, with a new prompt, so it is still you: you are the one resumed
470
- if this phase's work needs to run again. Re-read `$LEGION_WORKSPACE` and your own committed handoff
471
- then, without mutating anything until the new prompt asks for it (see Workspace and handoff
472
- precedence above).
470
+ **Stay in this session afterward.** Your process does not exit when your phase completes; it
471
+ stays live until your issue leaves the workflow. No move between phases stops it, and only an
472
+ explicit stop does: the issue closing; a move to `backlog`, `icebox` or `triage` (a child by a
473
+ person or its architect's `park_child`, or the root, which stops the whole tree); a child set back
474
+ to `todo` (which stops the interrupted phase's worker, not earlier roles); or an operator stop.
475
+ A stop keeps your session, and a crash relaunches it. Your next assignment arrives in this same
476
+ session. Other roles on
477
+ this issue may reach you through Envoy with
478
+ questions about the work you did — answer them, reading `$LEGION_WORKSPACE` and your own
479
+ committed handoff as needed, without mutating anything (see Workspace and handoff
480
+ precedence above). You will also be the one resumed, with a new prompt in this same
481
+ session, if this phase's work needs to run again.
473
482
 
474
483
  When blocked on a product, scope, design, lifecycle, or cross-phase decision, `envoy_publish` the
475
484
  owning architect a concise message: issue, phase, verified observation, what you tried, and the