@sjawhar/pi-legion-envoy 1.42.1 → 1.42.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/envoy.js CHANGED
@@ -30175,7 +30175,7 @@ var HANDOFF_SCHEMA_VERSION = 1;
30175
30175
  var HANDOFF_PHASES = ["architect", "plan", "implement", "test", "review"];
30176
30176
  var isoTimestamp = string2().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
30177
30177
  var handoffPhase = _enum2(HANDOFF_PHASES);
30178
- var nonEmpty = string2().min(1);
30178
+ var nonEmpty = string2().trim().min(1);
30179
30179
  var proofSchema = object({
30180
30180
  criterion: nonEmpty,
30181
30181
  surface: nonEmpty,
@@ -30195,7 +30195,7 @@ var baseHandoffSchema = object({
30195
30195
  completed: isoTimestamp,
30196
30196
  learningsInjected: array(string2()).optional(),
30197
30197
  learningsHelpful: array(string2()).optional()
30198
- });
30198
+ }).passthrough();
30199
30199
  var architectSchema = baseHandoffSchema.extend({
30200
30200
  phase: literal("architect"),
30201
30201
  scope: _enum2(["trivial", "small", "medium", "large"]).optional(),
@@ -30203,7 +30203,7 @@ var architectSchema = baseHandoffSchema.extend({
30203
30203
  subIssues: array(string2()).optional(),
30204
30204
  routingHints: routingHintsSchema,
30205
30205
  concerns: array(string2()).optional()
30206
- }).passthrough();
30206
+ });
30207
30207
  var requiredSkillsSchema = object({
30208
30208
  implement: array(string2()).optional(),
30209
30209
  test: array(string2()).optional(),
@@ -30217,7 +30217,7 @@ var planSchema = baseHandoffSchema.extend({
30217
30217
  concerns: array(string2()).optional(),
30218
30218
  workflowRecommendation: string2().optional(),
30219
30219
  requiredSkills: requiredSkillsSchema
30220
- }).passthrough();
30220
+ });
30221
30221
  var implementSchema = baseHandoffSchema.extend({
30222
30222
  phase: literal("implement"),
30223
30223
  filesChanged: array(string2()).optional(),
@@ -30228,7 +30228,7 @@ var implementSchema = baseHandoffSchema.extend({
30228
30228
  subPlanningNeeded: boolean2().optional(),
30229
30229
  discoveredComplexity: array(string2()).optional(),
30230
30230
  suggestedSubWorkers: number2().optional()
30231
- }).passthrough();
30231
+ });
30232
30232
  var testSchema = baseHandoffSchema.extend({
30233
30233
  phase: literal("test"),
30234
30234
  passed: number2().optional(),
@@ -30238,9 +30238,15 @@ var testSchema = baseHandoffSchema.extend({
30238
30238
  proof: array(proofSchema).min(1).optional(),
30239
30239
  documentationFeedback: string2().optional(),
30240
30240
  observations: array(string2()).optional()
30241
- }).passthrough().refine((handoff) => (handoff.failures?.length ?? 0) > 0 || (handoff.failed ?? 0) > 0 || (handoff.proof?.length ?? 0) > 0, {
30241
+ }).refine((handoff) => (handoff.failures?.length ?? 0) > 0 || (handoff.failed ?? 0) > 0 || (handoff.proof?.length ?? 0) > 0, {
30242
30242
  path: ["proof"],
30243
30243
  message: "a passing test handoff needs the tester's own production-like proof"
30244
+ }).refine((handoff) => (handoff.failed ?? 0) === 0 || (handoff.failures?.length ?? 0) > 0, {
30245
+ path: ["failures"],
30246
+ message: "a test handoff that reports failed > 0 records at least one failure"
30247
+ }).refine((handoff) => handoff.implementerProof.verdict !== "rejected" || (handoff.failures?.length ?? 0) > 0, {
30248
+ path: ["failures"],
30249
+ message: "a rejected implementer proof is a recorded failure"
30244
30250
  });
30245
30251
  var reviewSchema = baseHandoffSchema.extend({
30246
30252
  phase: literal("review"),
@@ -30249,7 +30255,7 @@ var reviewSchema = baseHandoffSchema.extend({
30249
30255
  minor: number2().optional(),
30250
30256
  verdict: _enum2(["approved", "changes_requested"]).optional(),
30251
30257
  keyFindings: array(object({ severity: string2(), file: string2(), description: string2() }).passthrough()).optional()
30252
- }).passthrough();
30258
+ });
30253
30259
  var phaseHandoffSchema = discriminatedUnion("phase", [
30254
30260
  architectSchema,
30255
30261
  planSchema,
package/dist/legion.js CHANGED
@@ -29449,7 +29449,7 @@ var HANDOFF_SCHEMA_VERSION = 1;
29449
29449
  var HANDOFF_PHASES = ["architect", "plan", "implement", "test", "review"];
29450
29450
  var isoTimestamp = string2().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
29451
29451
  var handoffPhase = _enum2(HANDOFF_PHASES);
29452
- var nonEmpty = string2().min(1);
29452
+ var nonEmpty = string2().trim().min(1);
29453
29453
  var proofSchema = object({
29454
29454
  criterion: nonEmpty,
29455
29455
  surface: nonEmpty,
@@ -29469,7 +29469,7 @@ var baseHandoffSchema = object({
29469
29469
  completed: isoTimestamp,
29470
29470
  learningsInjected: array(string2()).optional(),
29471
29471
  learningsHelpful: array(string2()).optional()
29472
- });
29472
+ }).passthrough();
29473
29473
  var architectSchema = baseHandoffSchema.extend({
29474
29474
  phase: literal("architect"),
29475
29475
  scope: _enum2(["trivial", "small", "medium", "large"]).optional(),
@@ -29477,7 +29477,7 @@ var architectSchema = baseHandoffSchema.extend({
29477
29477
  subIssues: array(string2()).optional(),
29478
29478
  routingHints: routingHintsSchema,
29479
29479
  concerns: array(string2()).optional()
29480
- }).passthrough();
29480
+ });
29481
29481
  var requiredSkillsSchema = object({
29482
29482
  implement: array(string2()).optional(),
29483
29483
  test: array(string2()).optional(),
@@ -29491,7 +29491,7 @@ var planSchema = baseHandoffSchema.extend({
29491
29491
  concerns: array(string2()).optional(),
29492
29492
  workflowRecommendation: string2().optional(),
29493
29493
  requiredSkills: requiredSkillsSchema
29494
- }).passthrough();
29494
+ });
29495
29495
  var implementSchema = baseHandoffSchema.extend({
29496
29496
  phase: literal("implement"),
29497
29497
  filesChanged: array(string2()).optional(),
@@ -29502,7 +29502,7 @@ var implementSchema = baseHandoffSchema.extend({
29502
29502
  subPlanningNeeded: boolean2().optional(),
29503
29503
  discoveredComplexity: array(string2()).optional(),
29504
29504
  suggestedSubWorkers: number2().optional()
29505
- }).passthrough();
29505
+ });
29506
29506
  var testSchema = baseHandoffSchema.extend({
29507
29507
  phase: literal("test"),
29508
29508
  passed: number2().optional(),
@@ -29512,9 +29512,15 @@ var testSchema = baseHandoffSchema.extend({
29512
29512
  proof: array(proofSchema).min(1).optional(),
29513
29513
  documentationFeedback: string2().optional(),
29514
29514
  observations: array(string2()).optional()
29515
- }).passthrough().refine((handoff) => (handoff.failures?.length ?? 0) > 0 || (handoff.failed ?? 0) > 0 || (handoff.proof?.length ?? 0) > 0, {
29515
+ }).refine((handoff) => (handoff.failures?.length ?? 0) > 0 || (handoff.failed ?? 0) > 0 || (handoff.proof?.length ?? 0) > 0, {
29516
29516
  path: ["proof"],
29517
29517
  message: "a passing test handoff needs the tester's own production-like proof"
29518
+ }).refine((handoff) => (handoff.failed ?? 0) === 0 || (handoff.failures?.length ?? 0) > 0, {
29519
+ path: ["failures"],
29520
+ message: "a test handoff that reports failed > 0 records at least one failure"
29521
+ }).refine((handoff) => handoff.implementerProof.verdict !== "rejected" || (handoff.failures?.length ?? 0) > 0, {
29522
+ path: ["failures"],
29523
+ message: "a rejected implementer proof is a recorded failure"
29518
29524
  });
29519
29525
  var reviewSchema = baseHandoffSchema.extend({
29520
29526
  phase: literal("review"),
@@ -29523,7 +29529,7 @@ var reviewSchema = baseHandoffSchema.extend({
29523
29529
  minor: number2().optional(),
29524
29530
  verdict: _enum2(["approved", "changes_requested"]).optional(),
29525
29531
  keyFindings: array(object({ severity: string2(), file: string2(), description: string2() }).passthrough()).optional()
29526
- }).passthrough();
29532
+ });
29527
29533
  var phaseHandoffSchema = discriminatedUnion("phase", [
29528
29534
  architectSchema,
29529
29535
  planSchema,
@@ -99,7 +99,7 @@ dispatch_message({
99
99
 
100
100
  **Proofs read:** implementer <surface/command>, tester <surface/command>.
101
101
 
102
- **Production check:** <what the implementer will drive after the merge, or the action ask it opened>
102
+ **Production check:** <what the implementer will drive after the merge, or the deploy/restart step a human will have to perform first>
103
103
 
104
104
  <!-- legion: {"session":"<session-id>","phase":"retro"} -->`,
105
105
  })
@@ -280,6 +280,25 @@ Verified the implementer's proof by <re-running its command | driving the same s
280
280
  **Retarget:** Retargeting a pull request to a new base does not re-run Tests; after a retarget, rebase onto the new base and push — the new head runs Tests against the new merge result — and cite that run in the PR body.
281
281
  ```
282
282
 
283
+ **A proof** is the changed behaviour exercised on the surface a user reaches it through, recorded
284
+ as the exact command or run id, what was observed, the head SHA, and one negative control —
285
+ a deliberately broken input and the refusal or failure it produced. The surface is
286
+ **production-like** — the repository's real-process test harness and fixtures, a sandbox
287
+ repository, a real browser, a devN stack, staging, or a local stack with real migrations, one that
288
+ has the resource the change touches — and each `E2E` line carries a **link** to that run,
289
+ screenshot, or e2e; the merge queue does not approve a user-facing change without it, and a
290
+ green unit suite is not it. A unit or integration test is a regression lock, never proof of a
291
+ criterion. Sami, 2026-09-13, verbatim: "They need to test everything in a production-like
292
+ environment before merging, and it is the agent that develops the feature that is responsible
293
+ for doing that. If there's anything blocking that, we need to fix it: if it's infrastructure, we
294
+ need to fix it; if it's tooling, we need to develop it; if it's skills, we need to fix the skills
295
+ ... it should not require deploying to production to realize your feature doesn't work."
296
+ Evidence for the rule: in the week of 2026-09-08 three surfaces merged green and were wrong on
297
+ inspection (the Astrolabe IPI stack, Dispatch on ECS, the candidate flow), and on 2026-09-12 six
298
+ deploy slots died on code first executed after merge, including a production-only ECS bootstrap
299
+ the whole staging gate never ran. The implementer's proof and the tester's proof below are both
300
+ this proof.
301
+
283
302
  - **Threads are dispositioned individually, never resolved in bulk.** Every open review
284
303
  thread gets its own line naming the fixing commit or the reason it isn't a defect. The
285
304
  reviewer answers each thread it opened with exactly one of `Accepted: fixed in <commit> — <one line>`,
@@ -319,40 +338,23 @@ Verified the implementer's proof by <re-running its command | driving the same s
319
338
  field names naming, duplication, or wording cleanup only; anything that changes behaviour,
320
339
  hides an error, or breaks a gate lands in this PR.
321
340
  - **The implementer proves the change before its phase completes, and writes the `E2E (implementer)` line when the pull request opens.**
322
- The proof is the changed behaviour exercised on the surface a user reaches it through — the daemon's
323
- test harness (`packages/daemon/src/daemon/__tests__/`) and real-process fixtures; a live check at the
324
- operator's next daemon restart, recorded on the PR; a sandbox repository, a real browser, a devN stack,
325
- or a local stack with real migrations — with the exact command or run id, what was observed, the head SHA,
326
- one negative control. The same proof goes into `.legion/implement.json` as its required `proof`
327
- array (`legion handoff write --phase implement` refuses a payload without one and names the
328
- field), and into the PR body, because the reviewer and the merger verify facts on GitHub and
329
- never from a handoff. A unit or integration test is a regression lock, never proof of a
330
- criterion.
341
+ The proof is the one defined above. It goes into `.legion/implement.json` as the required `proof`
342
+ array (`legion handoff write --phase implement` refuses a payload without one, or with a blank or
343
+ whitespace-only field, and names the field), and into the PR body, because the reviewer and the
344
+ merger verify facts on GitHub and never from a handoff.
331
345
  - **The tester verifies the implementer's proof and adds its own `E2E (tester)` line.** It re-runs
332
- the implementer's command or drives the same surface independently, records the verdict in
333
- `.legion/test.json` as `implementerProof` (`{verdict, how}`), and records its own proof beside
334
- it. A test handoff whose predecessor carried no proof is a test failure, not a gap for the tester to fill:
346
+ the implementer's command or drives the same surface independently, and records the verdict in
347
+ `.legion/test.json` as `implementerProof` (`{verdict, how}`).
348
+ A test handoff whose predecessor carried no proof is a test failure, not a gap for the tester to fill:
335
349
  record it in `failures` with `implementerProof.verdict: "rejected"`, complete the phase, and let
336
350
  the architect return the issue to the implementer — the agent that developed the change owns
337
- proving it. The tester's own proof names the real surface a user reaches the criterion
338
- through, the exact command or run id, what was observed, the head SHA, and one negative
339
- control — a deliberately broken input and the refusal or failure it produced. The surface is
340
- **production-like** — a devN stack, staging, or a local stack with real migrations, one that
341
- has the resource the change touches — and each `E2E` line carries a **link** to that run,
342
- screenshot, or e2e; the merge queue does not approve a user-facing change without it, and a
343
- green unit suite is not it. Sami, 2026-09-13, verbatim: "They need to test everything in a
344
- production-like environment before merging, and it is the agent that develops the feature
345
- that is responsible for doing that. If there's anything blocking that, we need to fix it: if
346
- it's infrastructure, we need to fix it; if it's tooling, we need to develop it; if it's
347
- skills, we need to fix the skills ... it should not require deploying to production to
348
- realize your feature doesn't work." A code path whose first execution is after merge — a
351
+ proving it (`legion handoff write --phase test` refuses a rejected verdict, or `failed > 0`,
352
+ with no recorded failure). Otherwise, add your own proof before completing — a proof as defined
353
+ above — as the `E2E (tester)` line and the `proof` array `legion handoff write --phase test`
354
+ requires whenever you report no failure. A code path whose first execution is after merge — a
349
355
  deploy workflow's inline step, a post-merge helper, a production-only resource — is untested
350
356
  until the implementer has executed it against a devN stack; if no surface can reach it, the
351
- tester names that missing surface as the blocker instead of passing the phase. Evidence for
352
- the rule: in the week of 2026-09-08 three surfaces merged green and were wrong on inspection
353
- (the Astrolabe IPI stack, Dispatch on ECS, the candidate flow), and on 2026-09-12 six deploy
354
- slots died on code first executed after merge, including a production-only ECS bootstrap the
355
- whole staging gate never ran. Environment or
357
+ tester names that missing surface as the blocker instead of passing the phase. Environment or
356
358
  secret-scrub evidence (e.g. "`LEGION_*`/`DISPATCH_*`/`ENVOY_*` unset") is recorded once, in
357
359
  `.legion/test.json`, and only when the issue's acceptance criteria call for it — never
358
360
  re-pasted into the PR body each round. After a conflict-forced rebase, compute the
@@ -536,10 +538,10 @@ and, for the implementer, until the push has too. This is the committed copy the
536
538
  reads after revival. It is removed once, at the end of a clean review: the implementer pushes
537
539
  that deletion at the reviewer's direction. No other phase removes it — and once it is gone
538
540
  (`jj -R "$LEGION_WORKSPACE" file list -r @- .legion` prints nothing on stdout; jj warns on
539
- stderr), this gate no longer applies: a later rebase, bare-gate re-check, confirmation, or retro
540
- writes no `.legion/<phase>.json`, commits no handoff, and reports with `legion handoff complete`
541
- alone (below). Recreating `.legion/` after its deletion changes the approved head and restarts
542
- the review loop this rule exists to end.
541
+ stderr), this gate no longer applies: a later rebase, bare-gate re-check, confirmation, retro, or
542
+ the post-merge production check writes no `.legion/<phase>.json`, commits no handoff, and reports
543
+ with `legion handoff complete` alone (below). Recreating `.legion/` after its deletion changes the
544
+ approved head and restarts the review loop this rule exists to end.
543
545
 
544
546
  ## Completion: report to the architect, then stay
545
547
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "1.42.1",
3
+ "version": "1.42.2",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [