@sjawhar/pi-legion-envoy 7.8.0 → 7.8.2

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/legion.js CHANGED
@@ -17555,7 +17555,7 @@ function endInjectedUserTurns(sessionID) {
17555
17555
  // package.json
17556
17556
  var package_default = {
17557
17557
  name: "@sjawhar/pi-legion-envoy",
17558
- version: "7.8.0",
17558
+ version: "7.8.2",
17559
17559
  license: "Apache-2.0",
17560
17560
  type: "module",
17561
17561
  omp: {
@@ -18491,7 +18491,7 @@ function handoffSchemaFields(z2) {
18491
18491
  ready: z2.boolean().optional()
18492
18492
  };
18493
18493
  }
18494
- var HANDOFF_DESCRIPTION = "Handoff actions (phase workers; the daemon accepts a completion only from the role working " + "the issue's current phase, never from an architect): handoff_write writes this phase's handoff " + "(`phase`, and `data`: the phase-specific fields as a JSON object, never the schemaVersion, " + "phase, completed and issue the command writes itself) to `.legion/<phase>.json` in " + "the issue workspace; handoff_read returns the handoffs (every phase, or `phase`); " + "handoff_complete reports this phase complete to the daemon (`summary`: two sentences for the " + "architect, or the merger's READY packet; `verdict` pass|fail when your role's instructions " + "require one; `ready: true` for the merger's READY; no `phase` is needed, and one other than " + "your own is refused). Each " + "returns the command's output; a failed action changed nothing. What a later phase needs goes " + "in your handoff; a question for another live role goes to its role topic with envoy_publish.";
18494
+ var HANDOFF_DESCRIPTION = "Handoff actions (phase workers; the daemon accepts a completion only from the role working " + "the issue's current phase, never from an architect): handoff_write writes this phase's handoff " + "(`phase`, and `data`: the phase-specific fields as a JSON object, never the schemaVersion, " + "phase, completed and issue the command writes itself) to `.legion/<issue>/<phase>.json` in " + "the issue workspace; handoff_read returns the handoffs (every phase, or `phase`); " + "handoff_complete reports this phase complete to the daemon (`summary`: two sentences for the " + "architect, or the merger's READY packet; `verdict` pass|fail when your role's instructions " + "require one; `ready: true` for the merger's READY; no `phase` is needed, and one other than " + "your own is refused). Each " + "returns the command's output; a failed action changed nothing. What a later phase needs goes " + "in your handoff; a question for another live role goes to its role topic with envoy_publish.";
18495
18495
  function rootArchitectHandoffRefusal(operation) {
18496
18496
  return `${operation} is not available to a root architect session; a root architect reads handoffs with \`legion handoff read [--phase <phase>]\` from bash`;
18497
18497
  }
@@ -86,7 +86,7 @@ The issue's primary document **is** the root specification. Extend it in place:
86
86
  that adds only the evidence each decision needs and what the human decides, each as a
87
87
  decision block (`skill://dispatch`, "Decision blocks"). The decomposition and its waves, how each
88
88
  outcome is proven, and the integration test are your own calls: they go in the child issues and
89
- the planner's `.legion/plan.json`, not the root spec. Never post a second "spec" artifact beside
89
+ the planner's `.legion/<issue>/plan.json`, not the root spec. Never post a second "spec" artifact beside
90
90
  it (`dispatch_artifact` with the primary document's name replaces the human's document; do not do
91
91
  that).
92
92
  The design gate's approval step runs only when the `Design gate policy` sentence of your
@@ -161,7 +161,7 @@ evidence the human did not weigh that would change the decision, such as a measu
161
161
  settled choice cannot meet the Acceptance; then that decision block names the decision and that
162
162
  evidence. A plan never overturns a settled decision on its own. A design change that leaves all
163
163
  four intact, such as a planner's measurement that finds a better way to build the same outcome,
164
- goes in the plan (the issue's `plan.md` document and `.legion/plan.json`), never into the approved
164
+ goes in the plan (the issue's `plan.md` document and `.legion/<issue>/plan.json`), never into the approved
165
165
  spec, even where the spec's text describes the older design; the reviewer reads the plan beside the
166
166
  spec. When a planner's phase-finished notice names a departure from the spec's design, defer to
167
167
  this section's full condition: only when the approved Summary, Acceptance, scope and settled
@@ -117,7 +117,8 @@ answer questions or to keep editing. Do not create new commits, run
117
117
  (and, for the implementer, pushed) — a code change belongs to whichever phase is active now.
118
118
 
119
119
  On every start, and especially after revival or re-creation, read the issue and then the
120
- committed predecessor handoffs in lifecycle order from `$LEGION_WORKSPACE/.legion/`:
120
+ committed predecessor handoffs in lifecycle order from
121
+ `$LEGION_WORKSPACE/.legion/<issue>/`:
121
122
 
122
123
  1. `architect.json`
123
124
  2. `plan.json`
@@ -131,11 +132,11 @@ untouched and reach the next worker. The `legion` tool's `handoff_read` returns
131
132
  stands in the workspace.
132
133
  Write the phase-specific fields the next phase and the architect need, consistent with what
133
134
  predecessor phases already wrote. The durable copy lives in
134
- `$LEGION_WORKSPACE/.legion/<phase>.json`. If a committed handoff conflicts with memory or a prior
135
+ `$LEGION_WORKSPACE/.legion/<issue>/<phase>.json`. If a committed handoff conflicts with memory or a prior
135
136
  transcript, the committed file wins: it is the copy that survived.
136
137
 
137
138
  If your system prompt begins with `Your workspace was recreated…`, read
138
- `.legion/workspace-recovered.json`, then your phase's committed handoff, and reconcile before any
139
+ `.legion/<issue>/workspace-recovered.json`, then your phase's committed handoff, and reconcile before any
139
140
  new work.
140
141
 
141
142
  ## jj Safety Rules
@@ -272,7 +273,7 @@ legion gh -- pr comment <pr-number> \
272
273
 
273
274
  ## Planner artifact
274
275
 
275
- The plan lives in `.legion/plan.json` and the issue's `plan.md` document, never in the issue's
276
+ The plan lives in `.legion/<issue>/plan.json` and the issue's `plan.md` document, never in the issue's
276
277
  primary document, which is its spec; never commit a plan or spec file to the repository.
277
278
  No `docs/plans/*`, `docs/superpowers/plans/*`, or spec markdown goes into the pull request: plan
278
279
  and spec content goes into the issue, never into a PR (the root `AGENTS.md`
@@ -281,7 +282,7 @@ to a file" is satisfied by the handoff write in the completion gate below; the p
281
282
  commit is `plan: record handoff`.
282
283
 
283
284
  A plan that departs from the spec's design records the departure in `plan.md` and in the required
284
- `.legion/plan.json` `specDepartures`: `[]` means no departure; otherwise each bounded record names
285
+ `.legion/<issue>/plan.json` `specDepartures`: `[]` means no departure; otherwise each bounded record names
285
286
  the spec, plan, evidence and outcome. The planner's role prompt defines that record. The planner
286
287
  never edits the spec. Whether the spec changes is the architect's decision
287
288
  (`skill://legion-architect`, section 1), and the reviewer reads the plan beside the spec.
@@ -338,13 +339,17 @@ line), the full definition of a proof, what the tester verifies, and the simplif
338
339
  The merger writes no handoff and pushes nothing, so this gate does not apply to it
339
340
  (`packages/daemon/internal/prompts/roles/merger.md`).
340
341
 
342
+ A planner picking up after the issue moves back from implementing starts fresh on the remote
343
+ tip — `jj -R "$LEGION_WORKSPACE" new legion/<KEY>@origin` — since the implementer's unpushed
344
+ commits are no longer in the chain (*Every role pushes its own commits*, below).
345
+
341
346
  Write the phase-specific handoff: call the `legion` tool with `op: "handoff_write"`, `phase: "<p>"`,
342
347
  and `data`: a JSON object of the phase-specific fields only. It runs `legion handoff write` in
343
348
  `$LEGION_WORKSPACE` and returns its output.
344
349
 
345
350
  A handoff built from the one already on disk (a test handoff that accumulates review rounds can
346
351
  pass 128 KiB) can instead be piped from bash, so you never re-emit the whole payload:
347
- `cd -- "$LEGION_WORKSPACE" && bun -e 'const h = await Bun.file(".legion/<phase>.json").json(); delete h.schemaVersion; delete h.phase; delete h.completed; <your edit to h>; console.log(JSON.stringify(h))' | legion handoff write --phase <phase>`.
352
+ `cd -- "$LEGION_WORKSPACE" && bun -e 'const h = await Bun.file(".legion/<issue>/<phase>.json").json(); delete h.schemaVersion; delete h.phase; delete h.completed; <your edit to h>; console.log(JSON.stringify(h))' | legion handoff write --phase <phase>`.
348
353
  The program is single-quoted, so strings in your edit take double quotes. It is `bun` because the
349
354
  worker image a pod runs ships `bun` and not `jq`, and a devbox pane has the `bun` Legion builds
350
355
  with. With `--data` omitted, `legion handoff write` reads the JSON object from stdin. The CLI adds
@@ -359,14 +364,14 @@ either phase, is an object of six non-empty strings: `criterion` (the acceptance
359
364
  Then verify the durable artifact exists:
360
365
 
361
366
  ```bash
362
- test -f "$LEGION_WORKSPACE/.legion/<phase>.json"
367
+ test -f "$LEGION_WORKSPACE/.legion/<issue>/<phase>.json"
363
368
  ```
364
369
 
365
370
  Then commit that exact handoff file onto the issue branch:
366
371
 
367
372
  ```bash
368
373
  cd -- "$LEGION_WORKSPACE" && \
369
- jj -R "$LEGION_WORKSPACE" split -m "<phase>: record handoff" .legion/<phase>.json
374
+ jj -R "$LEGION_WORKSPACE" split -m "<phase>: record handoff" .legion/<issue>/<phase>.json
370
375
  ```
371
376
 
372
377
  **Every role pushes its own commits.** After the handoff commit — and, for the tester, the red
@@ -378,11 +383,16 @@ cd -- "$LEGION_WORKSPACE" && legion push
378
383
 
379
384
  It pushes `@-` through the provisioned credential helper, which authenticates as your role's App
380
385
  (`appauth.AppRoleFor` in `packages/daemon/internal/appauth/identity.go`). Your system prompt says
381
- which pushes skip CI and which commit-message keywords it refuses. Its ancestry check refuses
386
+ which pushes skip CI and which commit-message keywords it refuses. While the head commit carries
387
+ `skip-checks: true`, a pull-request body edit alone starts no GitHub workflow run, so a check that
388
+ re-judges the body re-runs on that head only after a later push; on a code head the same edit
389
+ re-runs it at once. Its ancestry check refuses
382
390
  unless `@-` descends from `legion/<KEY>@origin` (or the branch is not on GitHub yet): every issue
383
391
  workspace shares one clone, so another role's push moves `legion/<KEY>@origin` here at once, and
384
392
  a push that did not descend from it would move the remote branch sideways onto your commit and
385
- drop theirs.
393
+ drop theirs. A handoff commit never sits on an implementer's unpushed chain: when the issue moves
394
+ back to planning, the implementer's unpushed commits stay off the bookmark until the implementer
395
+ returns, and the planner writes its handoff on the remote tip.
386
396
 
387
397
  Before any rewrite of a commit you already pushed — a `jj squash --into` one, or any other
388
398
  rewrite — read *Rewriting pushed commits* in
@@ -391,7 +401,7 @@ is built on that commit and records the pushed tip `legion push` reads, the only
391
401
  push lets the remote branch move off its current tip.
392
402
 
393
403
  Before the push, check ancestry and identity as above: the chain carries every earlier phase's
394
- commits, and pushing them with yours is expected. A refusal, and a push the remote rejects, is a
404
+ pushed commits, and pushing them with yours is expected. A refusal, and a push the remote rejects, is a
395
405
  report to the architect with the output, never a force-push. The merger makes no commit and
396
406
  pushes nothing.
397
407
 
@@ -400,8 +410,8 @@ succeed. This is the committed copy the next phase reads after revival. No phase
400
410
  `.legion/`: the reviewer approves a head that carries it. The daemon strips any `.legion/` still on
401
411
  main from the next issue's branch before any of its roles start (dispatch://LEGION-565), so that
402
412
  tree's own merge carries the removal onto the default branch; no operator sweep follows. Retro and
403
- the post-merge production check write no `.legion/<phase>.json`, commit no handoff, and report with
404
- `handoff_complete` alone (below).
413
+ the post-merge production check write no `.legion/<issue>/<phase>.json`, commit no handoff, and
414
+ report with `handoff_complete` alone (below).
405
415
 
406
416
  ## Completion: report to the architect, then stay
407
417
 
@@ -87,13 +87,13 @@ and the tester's proof below are both this proof.
87
87
  ## The rules every phase's evidence follows
88
88
 
89
89
  - **The implementer proves the change before its phase completes, and writes the `E2E (implementer)` line when the pull request opens.**
90
- The proof is the one defined above. It goes into `.legion/implement.json` as the required `proof`
90
+ The proof is the one defined above. It goes into `.legion/<issue>/implement.json` as the required `proof`
91
91
  array (`handoff_write` for phase `implement` refuses a payload without one, or with a blank or
92
92
  whitespace-only field, and names the field), and into the PR body, because the reviewer and the
93
93
  merger verify facts on GitHub and never from a handoff.
94
94
  - **The tester verifies the implementer's proof and adds its own `E2E (tester)` line.** It re-runs
95
95
  the implementer's command or drives the same surface independently, and records the verdict in
96
- `.legion/test.json` as `implementerProof` (`{verdict, how}`).
96
+ `.legion/<issue>/test.json` as `implementerProof` (`{verdict, how}`).
97
97
  A test handoff whose predecessor carried no proof is a test failure, not a gap for the tester to fill:
98
98
  record it in `failures` with `implementerProof.verdict: "rejected"`, complete the phase with
99
99
  `verdict: "fail"`, and the daemon returns the issue to the implementer — the agent that developed the change owns
@@ -105,7 +105,7 @@ and the tester's proof below are both this proof.
105
105
  until the implementer has executed it against a devN stack; if no surface can reach it, the
106
106
  tester names that missing surface as the blocker instead of passing the phase. Environment or
107
107
  secret-scrub evidence (e.g. "`LEGION_*`/`DISPATCH_*`/`ENVOY_*` unset") is recorded once, in
108
- `.legion/test.json`, and only when the issue's acceptance criteria call for it — never
108
+ `.legion/<issue>/test.json`, and only when the issue's acceptance criteria call for it — never
109
109
  re-pasted into the PR body each round. After a conflict-forced rebase, compute the
110
110
  fingerprint (*The unchanged-diff check* in
111
111
  `skill://legion-worker/references/conflicts-and-rewrites.md`) at the head your `E2E` line
@@ -129,6 +129,9 @@ and the tester's proof below are both this proof.
129
129
  `skill://legion-worker`): the `Fast-follow:` line holds naming, duplication, or wording cleanup
130
130
  only. A base frozen for others to stack on is never rewritten (*Rewriting pushed commits* in
131
131
  `skill://legion-worker/references/conflicts-and-rewrites.md`); the `Chain` line records it.
132
+ - **GitHub refuses a pull request body over 65,536 characters.** Each verification round links its
133
+ evidence (the run, the comment) rather than inlining it once the body passes about 48,000
134
+ characters; the `Production` line's record always links.
132
135
 
133
136
  ## When no surface reaches the changed path
134
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "7.8.0",
3
+ "version": "7.8.2",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {