@sjawhar/opencode-legion-envoy 1.39.0 → 1.40.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.
@@ -13599,6 +13599,12 @@ var askEventPayloadFields = {
13599
13599
  mark_id: string2().optional(),
13600
13600
  block_id: string2().nullable().optional()
13601
13601
  }).passthrough().nullish(),
13602
+ anchor_artifact: object({
13603
+ project: string2().optional(),
13604
+ slug: string2().optional(),
13605
+ name: string2().optional(),
13606
+ primary: boolean2().optional()
13607
+ }).optional(),
13602
13608
  resolution: object({
13603
13609
  kind: _enum2(["retracted", "resolved"]).optional(),
13604
13610
  reason: string2().optional(),
@@ -14277,12 +14283,19 @@ var stateIssue = strictObject({
14277
14283
  parent: nonEmptyString.optional(),
14278
14284
  lastAppliedSeq: number2().int().nonnegative().optional()
14279
14285
  });
14286
+ var stateWorkspaceLost = strictObject({
14287
+ at: nonEmptyString,
14288
+ generation: number2().int().nonnegative(),
14289
+ fromRef: nonEmptyString,
14290
+ previousSessionId: nonEmptyString.optional()
14291
+ });
14280
14292
  var stateTree = strictObject({
14281
14293
  status: _enum2(TREE_STATUSES),
14282
14294
  generation: number2().int().nonnegative(),
14283
14295
  launchFailures: number2().int().nonnegative(),
14284
14296
  readyConfirmedAt: number2().optional(),
14285
- locator: stateTreeLocator.optional()
14297
+ locator: stateTreeLocator.optional(),
14298
+ workspaceLost: stateWorkspaceLost.optional()
14286
14299
  });
14287
14300
  var stateGate = strictObject({
14288
14301
  artifactId: nonEmptyString,
@@ -14296,7 +14309,8 @@ var stateRole = strictObject({
14296
14309
  sessionId: nonEmptyString.optional(),
14297
14310
  readyConfirmedAt: number2().optional(),
14298
14311
  launchFailures: number2().int().nonnegative().optional(),
14299
- locator: stateLocator.optional()
14312
+ locator: stateLocator.optional(),
14313
+ workspaceLost: stateWorkspaceLost.optional()
14300
14314
  });
14301
14315
  var stateQueuedWorkerIdentity = {
14302
14316
  roleToken: nonEmptyString,
@@ -14335,7 +14349,8 @@ var LegionDaemonApi = {
14335
14349
  request: strictObject({
14336
14350
  secret: nonEmptyString,
14337
14351
  sessionId: nonEmptyString,
14338
- ompSessionFile: nonEmptyString.optional()
14352
+ ompSessionFile: nonEmptyString.optional(),
14353
+ pluginVersion: nonEmptyString
14339
14354
  }),
14340
14355
  response: object({})
14341
14356
  },
@@ -14350,7 +14365,8 @@ var LegionDaemonApi = {
14350
14365
  rootSessionId: nonEmptyString,
14351
14366
  agentId: nonEmptyString,
14352
14367
  bootToken: nonEmptyString,
14353
- ompSessionFile: nonEmptyString
14368
+ ompSessionFile: nonEmptyString,
14369
+ pluginVersion: nonEmptyString
14354
14370
  }),
14355
14371
  response: object({
14356
14372
  roleTokens: record(string2(), string2()),
@@ -14392,7 +14408,8 @@ var LegionDaemonApi = {
14392
14408
  bootToken: nonEmptyString,
14393
14409
  sessionId: nonEmptyString,
14394
14410
  agentId: nonEmptyString,
14395
- ompSessionFile: nonEmptyString
14411
+ ompSessionFile: nonEmptyString,
14412
+ pluginVersion: nonEmptyString
14396
14413
  }),
14397
14414
  response: object({
14398
14415
  roleToken: nonEmptyString,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "1.39.0",
3
+ "version": "1.40.1",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -308,6 +308,7 @@ active phase worker.
308
308
  | `phase-complete` | Payload `{type:"phase-complete", issue, role, summary}`. May arrive live or via `catchup-overseer`'s `phaseCompletions`. Read the committed handoff for that phase, then spawn the next phase's owner, or `spawn_worker` on the same role again to resume it with corrections if the handoff shows unresolved gaps. A `reviewer` completion whose GitHub review is `CHANGES_REQUESTED` (the daemon returns the issue's Dispatch status to `in_progress` for this, on the reviewer's completion and again when you spawn the corrective implementer unless the daemon already knows the issue is `in_progress`) means `spawn_worker` the **implementer** again with the review findings — thread URLs and blocking items — as its task, then route back through tester and reviewer in order; never `spawn_worker` the reviewer directly off this wake and never proceed to retro on this verdict. A reviewer completion with an `APPROVED` review proceeds to retro (step 5). A `reviewer` completion after a conflict-forced rebase whose review body names an unchanged fingerprint is a confirmation, not a round: if retro already completed, `spawn_worker` the merger; otherwise resume the step you were on. An `implementer` completion that follows the merge is its production report: read the record on the pull request and the issue, then run step 7 — the issue is already at `retro`, the daemon writes no status for this completion, and you set `done` yourself. A `tester` completion whose handoff carries `implementerProof.verdict: "rejected"`, or a failure naming the production-like proof, goes back to the **implementer** with that finding — never forward to the reviewer, and never by supplying the proof from another role. A worker that reports no surface reaches the changed path gets a child issue in this tree (infrastructure, tooling, or a skill) and a resume once it lands; that report is never a reason to advance the phase. |
309
309
  | `worker-queued` | Payload `{type:"worker-queued", issue, role}`. This role's task is queued for promotion — either the deployment's worker cap is full, or the live worker acknowledged the task without starting a turn and the daemon is retrying it (counted; the worker is replaced after three such failures, still with the same task). Do not respawn or retry — wait for `worker-started`. `legion state` shows the queue (`workerAdmission.queue`: role token, issue, role, kind, and the time the task was first queued — never the task text); read it before re-sending. A `spawn_worker` identical to the queued task changes nothing and is not announced again. Different text replaces the queued task silently in the same FIFO slot and retains its original queue time. A `spawn_worker` that fails with "got no response in 3 attempts" was already retried by the plugin under one request id and may still have reached the daemon: read the queue and the role's claim in `legion state` before sending it again. |
310
310
  | `worker-started` | Payload `{type:"worker-started", issue, role}`. A previously queued role has been promoted and is now running. Treat it exactly as a normal spawn: resume tracking that role's live session. |
311
+ | `worker-recovered` | Payload `{type:"worker-recovered", issue, role, fromRef, delivery?}`. The worker's tree volume was lost and the daemon replaced it from the committed handoff on `fromRef`. `delivery: "spawned"` means the current assignment was preserved on the new worker; do not resend it. `delivery: "queued"` means that preserved assignment awaits capacity; wait for `worker-started`. Without `delivery`, inspect `.legion/` and the active phase before deciding whether work needs a new assignment. |
311
312
  | `pr-ready` | Verify the live PR head, green status, and review state. Continue the review/retro/merger order only for that current head. |
312
313
  | `pr-review` | Payload `{type:"pr-review", state, author, body}`. Delivered to whichever role is currently active for the issue, falling back to you when no worker phase is active. Follows the same verdict rule as a reviewer's `phase-complete`: `state: "changes_requested"` sends the implementer back in with the review findings, then tester, then reviewer — never the reviewer again and never retro; that `spawn_worker` returns the issue to `in_progress` on its own (the daemon writes it for a corrective implementer whenever the PR's latest recorded review is changes requested, a human's after approval included), so you set nothing by hand; `state: "approved"` proceeds toward retro (step 5) once the step 6 integration/merge-gate conditions are met. `state: "approved"` on a rebased head whose body names an unchanged fingerprint is that confirmation: proceed to retro if it has not run, otherwise to the merger — never to a second retro or test round. |
313
314
  | `pr-blocked` | Payload `{type:"pr-blocked", pr, attempts}`. `attempts` counts heads pushed onto a red verdict that changed something outside `.legion/` — handoff-only pushes (`.legion/` paths only) never count; a push the daemon cannot classify (a listener without `changed_paths`, a list capped at 100, a push listing no commits) does. Published once per exhausted count, not on every later red verdict for that count. Read the failed CI evidence and recovery attempts. Assign a focused implementer or corrective child, then return it through testing and review; do not treat the blocked PR as final. |
@@ -112,6 +112,7 @@ quoted here.
112
112
  | `child-status` | child key + status transition | Not controller-actionable by default; if the daemon could not route it to the parent's architect role, verify the transition and forward it with `envoy_publish` |
113
113
  | Mention | Slack/GitHub PR @mention text | Answer, or route to the owning issue's architect role |
114
114
  | READY packet seen on a Dispatch issue (via issue subscription) | READY line + gate facts | No action: a human merges; the merger has already notified the queue role if the project has one |
115
+ | `worker-recovered` (role `architect`) from the daemon | issue, fromRef | A root architect's tree volume was lost; it restarted as a new session. Verify the tree is active in `legion state` and that the architect posts its next step on the issue within one resync interval; otherwise treat it as an anomaly. |
115
116
  | Closed-tree activity (comment, review, CI on a closed tree) | issue, root, event summary | Read the artifact; if work should resume, `legion status <root> todo`; otherwise no action — the event is not held or redelivered |
116
117
  | Direct user message | — | Always first |
117
118
 
@@ -111,6 +111,10 @@ predecessor phases already wrote. The durable copy lives in
111
111
  `$LEGION_WORKSPACE/.legion/<phase>.json`. If a committed handoff conflicts with memory or a prior
112
112
  transcript, the committed file wins: it is the copy that survived.
113
113
 
114
+ If your system prompt begins with `Your workspace was recreated…`, read
115
+ `.legion/workspace-recovered.json`, then your phase's committed handoff, and reconcile before any
116
+ new work.
117
+
114
118
  ## jj Safety Rules
115
119
 
116
120
  - **Always `jj -R "$LEGION_WORKSPACE" new` to create isolated commits.** Never