@sjawhar/pi-legion-envoy 5.28.0 → 5.29.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.
- package/README.md +4 -3
- package/agents/plan-gap-analyst.md +52 -0
- package/agents/plan-reviewer.md +61 -0
- package/dist/envoy.js +67 -6
- package/dist/legion.js +65 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,9 +71,10 @@ at `dist/skills`. The manifest declares `omp.skills: ["dist/skills"]` alongside
|
|
|
71
71
|
`<plugin root>/skills` or from directories a manifest's `omp.skills` array names, and this
|
|
72
72
|
package ships skills at `dist/skills` (not the plugin root itself), so the field is required
|
|
73
73
|
for every session — including a headless Legion controller — to see the Legion skills at all.
|
|
74
|
-
The tarball also ships `agents/`, the task agents Legion's prompts dispatch (`oracle
|
|
75
|
-
reviewer's pair `thermonuclear-deep-review` and `thermonuclear-code-quality
|
|
76
|
-
which writes the implementer's code
|
|
74
|
+
The tarball also ships `agents/`, the task agents Legion's prompts dispatch (`oracle`; the
|
|
75
|
+
reviewer's pair `thermonuclear-deep-review` and `thermonuclear-code-quality`; `deep-worker`,
|
|
76
|
+
which writes the implementer's code; and the planner's checks, `plan-gap-analyst` before it drafts
|
|
77
|
+
and `plan-reviewer` after), which Oh My Pi discovers under any extension package root:
|
|
77
78
|
an installed plugin in a pane, the explicit `--extension` root in a Sandbox pod. Each declares its
|
|
78
79
|
model as a role the operator maps (`docs/kubernetes.md`, "Model roles"). The skills those agents and the
|
|
79
80
|
role prompts load (the pair's rubrics, the implementer's `ce-simplify-code`) ship in
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan-gap-analyst
|
|
3
|
+
description: |
|
|
4
|
+
Pre-planning gap analyst. Read-only. Use before drafting a plan: finds the hidden requirements,
|
|
5
|
+
ambiguities, and missing machine-checkable acceptance criteria an issue leaves unsaid, each with
|
|
6
|
+
what the plan must answer.
|
|
7
|
+
# @oracle is the deployment's `oracle` model role; the Go daemon's boot gate refuses to start unless the operator's settings give
|
|
8
|
+
# this agent a model, through modelRoles.oracle or a task.agentModelOverrides entry for it (docs/kubernetes.md, Operator configuration).
|
|
9
|
+
model: ["@oracle"]
|
|
10
|
+
tools: read, glob, grep, todo
|
|
11
|
+
# The planner waits for the analysis before it drafts; without this, Oh My Pi runs a task agent in
|
|
12
|
+
# the background whenever async jobs are enabled.
|
|
13
|
+
blocking: true
|
|
14
|
+
color: yellow
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You read an issue before its plan exists and find what the issue leaves unsaid that would derail
|
|
18
|
+
the plan. You advise the planner; the planner owns the plan.
|
|
19
|
+
|
|
20
|
+
## What you look for
|
|
21
|
+
|
|
22
|
+
1. **Hidden requirements.** What the change needs but the issue does not state: a caller, contract,
|
|
23
|
+
migration, configuration, document, or consumer the change reaches; a behaviour the existing
|
|
24
|
+
code promises that the change must keep.
|
|
25
|
+
2. **Ambiguities.** A sentence with two readings that lead to different work. Name both readings
|
|
26
|
+
and what each would cost.
|
|
27
|
+
3. **Acceptance a machine cannot check.** A criterion with no command, test, or request whose
|
|
28
|
+
expected output decides it, or a requirement with no criterion at all.
|
|
29
|
+
|
|
30
|
+
Read the code and the repository's own documentation before you call something a gap. A gap the
|
|
31
|
+
issue, the code, or the documentation already answers is not a finding.
|
|
32
|
+
|
|
33
|
+
## What a finding contains
|
|
34
|
+
|
|
35
|
+
- **The gap**, quoting the issue's words where it has them.
|
|
36
|
+
- **The evidence**: the file and line, or the issue text, that shows it.
|
|
37
|
+
- **What the plan must answer**: the question or decision the plan has to settle and, for an
|
|
38
|
+
acceptance gap, a check a machine could run. Say whether the code settles it or only the
|
|
39
|
+
issue's owner can (a product choice).
|
|
40
|
+
|
|
41
|
+
Report the findings that change the plan, the most work-changing first. Style, edge cases the plan
|
|
42
|
+
can settle in passing, and the design you would have chosen are not findings. When nothing changes
|
|
43
|
+
the plan, say so in one line.
|
|
44
|
+
|
|
45
|
+
## Constraints
|
|
46
|
+
|
|
47
|
+
- **Read-only: you analyse; you do not implement.** Your file tools are read-only; do not ask for
|
|
48
|
+
others or route edits through other means. Your session also carries the Dispatch and Envoy
|
|
49
|
+
tools: read with them if you need to, but write nothing through them — no issue, comment, ask,
|
|
50
|
+
message, suggestion or document edit, and nothing sent or published.
|
|
51
|
+
- Cite what you read. Anything you did not read is an assumption and is written as one.
|
|
52
|
+
- Do not write the plan.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan-reviewer
|
|
3
|
+
description: |
|
|
4
|
+
Plan executability reviewer. Read-only. Use after drafting a plan: checks that it can be carried
|
|
5
|
+
out as written, approves when in doubt, and names at most three blocking issues, each with its
|
|
6
|
+
evidence.
|
|
7
|
+
# @review is the deployment's `review` model role; the Go daemon's boot gate refuses to start unless the operator's settings give
|
|
8
|
+
# this agent a model, through modelRoles.review or a task.agentModelOverrides entry for it (docs/kubernetes.md, Operator configuration).
|
|
9
|
+
model: ["@review"]
|
|
10
|
+
tools: read, glob, grep, todo
|
|
11
|
+
# The planner waits for each verdict before it revises or proceeds; without this, Oh My Pi runs a
|
|
12
|
+
# task agent in the background whenever async jobs are enabled.
|
|
13
|
+
blocking: true
|
|
14
|
+
color: magenta
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You answer one question: can a capable engineer who has only this plan and the repository carry
|
|
18
|
+
it out without getting stuck? You find blockers, not improvements. You advise the planner; the
|
|
19
|
+
planner owns the plan.
|
|
20
|
+
|
|
21
|
+
## What you check
|
|
22
|
+
|
|
23
|
+
1. **References.** The files, functions, commands, and skills the plan names exist and hold what
|
|
24
|
+
the plan says. Read them; do not assume.
|
|
25
|
+
2. **A place to start.** Every task says where the work is and what changes, in an order that can
|
|
26
|
+
be followed.
|
|
27
|
+
3. **Contradictions.** No two steps contradict each other, and no step contradicts the issue's
|
|
28
|
+
acceptance criteria.
|
|
29
|
+
4. **Runnable checks.** Every acceptance criterion names the surface and the exact command that
|
|
30
|
+
decides it.
|
|
31
|
+
|
|
32
|
+
You do not judge whether the approach is the best one, style, naming, edge cases the engineer can
|
|
33
|
+
settle during the work, or anything you would simply do differently.
|
|
34
|
+
|
|
35
|
+
## Verdict
|
|
36
|
+
|
|
37
|
+
Approve when in doubt. A plan that is mostly clear is good enough. Reject only for a blocker: a
|
|
38
|
+
reference that does not exist or does not hold what the plan says (read to confirm), a task with
|
|
39
|
+
nowhere to start, a contradiction, or a criterion nothing can check.
|
|
40
|
+
|
|
41
|
+
A rejection names at most three blocking issues, the most severe first. Each gives:
|
|
42
|
+
|
|
43
|
+
- **The issue**: the exact task, step, or criterion.
|
|
44
|
+
- **The evidence**: the file and line you read, or the plan's own words.
|
|
45
|
+
- **What must change** for it to pass.
|
|
46
|
+
|
|
47
|
+
A revised plan is read again in full and judged fresh: an issue the revision resolved is not
|
|
48
|
+
raised again, and a second round is no place for requests that would not have blocked the first.
|
|
49
|
+
|
|
50
|
+
## Output
|
|
51
|
+
|
|
52
|
+
The first line is the verdict alone: `approved` or `rejected`. Then one or two sentences on why.
|
|
53
|
+
On `rejected`, the numbered blocking issues. Nothing else.
|
|
54
|
+
|
|
55
|
+
## Constraints
|
|
56
|
+
|
|
57
|
+
- **Read-only: you review; you do not implement.** Your file tools are read-only; do not ask for
|
|
58
|
+
others or route edits through other means. Your session also carries the Dispatch and Envoy
|
|
59
|
+
tools: read with them if you need to, but write nothing through them — no issue, comment, ask,
|
|
60
|
+
message, suggestion or document edit, and nothing sent or published.
|
|
61
|
+
- Do not rewrite the plan.
|
package/dist/envoy.js
CHANGED
|
@@ -30477,6 +30477,8 @@ var EnvelopeSchema = exports_external.object({
|
|
|
30477
30477
|
// ../contracts/src/handoff-schema.ts
|
|
30478
30478
|
var HANDOFF_SCHEMA_VERSION = 1;
|
|
30479
30479
|
var HANDOFF_PHASES = ["architect", "plan", "implement", "test", "review"];
|
|
30480
|
+
var PLAN_REVIEW_MAX_ROUNDS = 3;
|
|
30481
|
+
var PLAN_REVIEW_VERDICTS = ["approved", "rejected", "failed"];
|
|
30480
30482
|
var isoTimestamp = exports_external.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
|
30481
30483
|
var handoffPhase = exports_external.enum(HANDOFF_PHASES);
|
|
30482
30484
|
var nonEmpty = exports_external.string().trim().min(1);
|
|
@@ -30513,6 +30515,16 @@ var requiredSkillsSchema = exports_external.object({
|
|
|
30513
30515
|
test: exports_external.array(exports_external.string()).optional(),
|
|
30514
30516
|
review: exports_external.array(exports_external.string()).optional()
|
|
30515
30517
|
}).passthrough().optional();
|
|
30518
|
+
var gapAnalysisSchema = exports_external.object({
|
|
30519
|
+
findings: exports_external.array(exports_external.object({ finding: exports_external.string(), answer: exports_external.string() }).passthrough()).optional(),
|
|
30520
|
+
error: exports_external.string().optional()
|
|
30521
|
+
}).passthrough().optional();
|
|
30522
|
+
var planReviewSchema = exports_external.object({
|
|
30523
|
+
verdict: exports_external.enum(PLAN_REVIEW_VERDICTS),
|
|
30524
|
+
rounds: exports_external.number(),
|
|
30525
|
+
remainingIssues: exports_external.array(exports_external.object({ issue: exports_external.string(), evidence: exports_external.string() }).passthrough()).optional(),
|
|
30526
|
+
error: exports_external.string().optional()
|
|
30527
|
+
}).passthrough().optional();
|
|
30516
30528
|
var planSchema = baseHandoffSchema.extend({
|
|
30517
30529
|
phase: exports_external.literal("plan"),
|
|
30518
30530
|
taskCount: exports_external.number().optional(),
|
|
@@ -30520,7 +30532,9 @@ var planSchema = baseHandoffSchema.extend({
|
|
|
30520
30532
|
routingHints: routingHintsSchema,
|
|
30521
30533
|
concerns: exports_external.array(exports_external.string()).optional(),
|
|
30522
30534
|
workflowRecommendation: exports_external.string().optional(),
|
|
30523
|
-
requiredSkills: requiredSkillsSchema
|
|
30535
|
+
requiredSkills: requiredSkillsSchema,
|
|
30536
|
+
gapAnalysis: gapAnalysisSchema,
|
|
30537
|
+
planReview: planReviewSchema
|
|
30524
30538
|
});
|
|
30525
30539
|
var implementSchema = baseHandoffSchema.extend({
|
|
30526
30540
|
phase: exports_external.literal("implement"),
|
|
@@ -30560,13 +30574,60 @@ var reviewSchema = baseHandoffSchema.extend({
|
|
|
30560
30574
|
verdict: exports_external.enum(["approved", "changes_requested"]).optional(),
|
|
30561
30575
|
keyFindings: exports_external.array(exports_external.object({ severity: exports_external.string(), file: exports_external.string(), description: exports_external.string() }).passthrough()).optional()
|
|
30562
30576
|
});
|
|
30563
|
-
var nonEmptySkillList = exports_external.array(
|
|
30577
|
+
var nonEmptySkillList = exports_external.array(nonEmpty).min(1);
|
|
30578
|
+
var recorded = (shape, whatToRecord) => exports_external.object(shape, {
|
|
30579
|
+
error: (issue2) => issue2.input === undefined ? `missing \u2014 record ${whatToRecord}` : undefined
|
|
30580
|
+
}).passthrough();
|
|
30581
|
+
var gapAnalysisWriteSchema = recorded({
|
|
30582
|
+
findings: exports_external.array(exports_external.object({ finding: nonEmpty, answer: nonEmpty }).passthrough()).optional(),
|
|
30583
|
+
error: nonEmpty.optional()
|
|
30584
|
+
}, "the gap analyst's `findings`, each with how the plan answers it (`[]` when it found none), or its failed call's `error`").refine((analysis) => analysis.findings === undefined !== (analysis.error === undefined), {
|
|
30585
|
+
message: "record exactly one of `findings` or the failed call's `error`"
|
|
30586
|
+
});
|
|
30587
|
+
var planReviewWriteSchema = recorded({
|
|
30588
|
+
verdict: exports_external.enum(PLAN_REVIEW_VERDICTS),
|
|
30589
|
+
rounds: exports_external.number().int().min(1).max(PLAN_REVIEW_MAX_ROUNDS),
|
|
30590
|
+
remainingIssues: exports_external.array(exports_external.object({ issue: nonEmpty, evidence: nonEmpty }).passthrough()).optional(),
|
|
30591
|
+
error: nonEmpty.optional()
|
|
30592
|
+
}, "the plan review's `verdict` and `rounds`, with `remainingIssues` when it was rejected or `error` when a review's call failed").superRefine((review, ctx) => {
|
|
30593
|
+
const remaining = review.remainingIssues?.length ?? 0;
|
|
30594
|
+
if (review.verdict === "rejected" && remaining === 0) {
|
|
30595
|
+
ctx.addIssue({
|
|
30596
|
+
code: "custom",
|
|
30597
|
+
path: ["remainingIssues"],
|
|
30598
|
+
message: "a rejected review records the blocking issues its last round named"
|
|
30599
|
+
});
|
|
30600
|
+
}
|
|
30601
|
+
if (review.verdict === "rejected" && review.rounds < PLAN_REVIEW_MAX_ROUNDS) {
|
|
30602
|
+
ctx.addIssue({
|
|
30603
|
+
code: "custom",
|
|
30604
|
+
path: ["rounds"],
|
|
30605
|
+
message: `a review still rejecting after ${review.rounds} of ${PLAN_REVIEW_MAX_ROUNDS} rounds is revised and reviewed again, not recorded`
|
|
30606
|
+
});
|
|
30607
|
+
}
|
|
30608
|
+
if (review.verdict === "approved" && remaining > 0) {
|
|
30609
|
+
ctx.addIssue({
|
|
30610
|
+
code: "custom",
|
|
30611
|
+
path: ["remainingIssues"],
|
|
30612
|
+
message: "an approved review leaves no blocking issue standing"
|
|
30613
|
+
});
|
|
30614
|
+
}
|
|
30615
|
+
if (review.verdict === "failed" !== (review.error !== undefined)) {
|
|
30616
|
+
ctx.addIssue({
|
|
30617
|
+
code: "custom",
|
|
30618
|
+
path: ["error"],
|
|
30619
|
+
message: "a failed review records its call's error, and only a failed review does"
|
|
30620
|
+
});
|
|
30621
|
+
}
|
|
30622
|
+
});
|
|
30564
30623
|
var planWriteSchema = planSchema.extend({
|
|
30565
30624
|
requiredSkills: exports_external.object({
|
|
30566
30625
|
implement: nonEmptySkillList,
|
|
30567
30626
|
test: nonEmptySkillList,
|
|
30568
30627
|
review: nonEmptySkillList
|
|
30569
|
-
}).passthrough()
|
|
30628
|
+
}).passthrough(),
|
|
30629
|
+
gapAnalysis: gapAnalysisWriteSchema,
|
|
30630
|
+
planReview: planReviewWriteSchema
|
|
30570
30631
|
});
|
|
30571
30632
|
var phaseHandoffSchema = exports_external.discriminatedUnion("phase", [
|
|
30572
30633
|
architectSchema,
|
|
@@ -35400,9 +35461,9 @@ function resolveEnvoySession(sessionFile) {
|
|
|
35400
35461
|
const parent = `${directory}.jsonl`;
|
|
35401
35462
|
if (parent === candidate)
|
|
35402
35463
|
break;
|
|
35403
|
-
const
|
|
35404
|
-
if (
|
|
35405
|
-
return
|
|
35464
|
+
const recorded2 = sessions.get(parent);
|
|
35465
|
+
if (recorded2 !== undefined)
|
|
35466
|
+
return recorded2;
|
|
35406
35467
|
if (path2.dirname(directory) === directory)
|
|
35407
35468
|
break;
|
|
35408
35469
|
candidate = parent;
|
package/dist/legion.js
CHANGED
|
@@ -30646,6 +30646,8 @@ var EnvelopeSchema = exports_external.object({
|
|
|
30646
30646
|
// ../contracts/src/handoff-schema.ts
|
|
30647
30647
|
var HANDOFF_SCHEMA_VERSION = 1;
|
|
30648
30648
|
var HANDOFF_PHASES = ["architect", "plan", "implement", "test", "review"];
|
|
30649
|
+
var PLAN_REVIEW_MAX_ROUNDS = 3;
|
|
30650
|
+
var PLAN_REVIEW_VERDICTS = ["approved", "rejected", "failed"];
|
|
30649
30651
|
var isoTimestamp = exports_external.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
|
30650
30652
|
var handoffPhase = exports_external.enum(HANDOFF_PHASES);
|
|
30651
30653
|
var nonEmpty = exports_external.string().trim().min(1);
|
|
@@ -30682,6 +30684,16 @@ var requiredSkillsSchema = exports_external.object({
|
|
|
30682
30684
|
test: exports_external.array(exports_external.string()).optional(),
|
|
30683
30685
|
review: exports_external.array(exports_external.string()).optional()
|
|
30684
30686
|
}).passthrough().optional();
|
|
30687
|
+
var gapAnalysisSchema = exports_external.object({
|
|
30688
|
+
findings: exports_external.array(exports_external.object({ finding: exports_external.string(), answer: exports_external.string() }).passthrough()).optional(),
|
|
30689
|
+
error: exports_external.string().optional()
|
|
30690
|
+
}).passthrough().optional();
|
|
30691
|
+
var planReviewSchema = exports_external.object({
|
|
30692
|
+
verdict: exports_external.enum(PLAN_REVIEW_VERDICTS),
|
|
30693
|
+
rounds: exports_external.number(),
|
|
30694
|
+
remainingIssues: exports_external.array(exports_external.object({ issue: exports_external.string(), evidence: exports_external.string() }).passthrough()).optional(),
|
|
30695
|
+
error: exports_external.string().optional()
|
|
30696
|
+
}).passthrough().optional();
|
|
30685
30697
|
var planSchema = baseHandoffSchema.extend({
|
|
30686
30698
|
phase: exports_external.literal("plan"),
|
|
30687
30699
|
taskCount: exports_external.number().optional(),
|
|
@@ -30689,7 +30701,9 @@ var planSchema = baseHandoffSchema.extend({
|
|
|
30689
30701
|
routingHints: routingHintsSchema,
|
|
30690
30702
|
concerns: exports_external.array(exports_external.string()).optional(),
|
|
30691
30703
|
workflowRecommendation: exports_external.string().optional(),
|
|
30692
|
-
requiredSkills: requiredSkillsSchema
|
|
30704
|
+
requiredSkills: requiredSkillsSchema,
|
|
30705
|
+
gapAnalysis: gapAnalysisSchema,
|
|
30706
|
+
planReview: planReviewSchema
|
|
30693
30707
|
});
|
|
30694
30708
|
var implementSchema = baseHandoffSchema.extend({
|
|
30695
30709
|
phase: exports_external.literal("implement"),
|
|
@@ -30729,13 +30743,60 @@ var reviewSchema = baseHandoffSchema.extend({
|
|
|
30729
30743
|
verdict: exports_external.enum(["approved", "changes_requested"]).optional(),
|
|
30730
30744
|
keyFindings: exports_external.array(exports_external.object({ severity: exports_external.string(), file: exports_external.string(), description: exports_external.string() }).passthrough()).optional()
|
|
30731
30745
|
});
|
|
30732
|
-
var nonEmptySkillList = exports_external.array(
|
|
30746
|
+
var nonEmptySkillList = exports_external.array(nonEmpty).min(1);
|
|
30747
|
+
var recorded = (shape, whatToRecord) => exports_external.object(shape, {
|
|
30748
|
+
error: (issue2) => issue2.input === undefined ? `missing \u2014 record ${whatToRecord}` : undefined
|
|
30749
|
+
}).passthrough();
|
|
30750
|
+
var gapAnalysisWriteSchema = recorded({
|
|
30751
|
+
findings: exports_external.array(exports_external.object({ finding: nonEmpty, answer: nonEmpty }).passthrough()).optional(),
|
|
30752
|
+
error: nonEmpty.optional()
|
|
30753
|
+
}, "the gap analyst's `findings`, each with how the plan answers it (`[]` when it found none), or its failed call's `error`").refine((analysis) => analysis.findings === undefined !== (analysis.error === undefined), {
|
|
30754
|
+
message: "record exactly one of `findings` or the failed call's `error`"
|
|
30755
|
+
});
|
|
30756
|
+
var planReviewWriteSchema = recorded({
|
|
30757
|
+
verdict: exports_external.enum(PLAN_REVIEW_VERDICTS),
|
|
30758
|
+
rounds: exports_external.number().int().min(1).max(PLAN_REVIEW_MAX_ROUNDS),
|
|
30759
|
+
remainingIssues: exports_external.array(exports_external.object({ issue: nonEmpty, evidence: nonEmpty }).passthrough()).optional(),
|
|
30760
|
+
error: nonEmpty.optional()
|
|
30761
|
+
}, "the plan review's `verdict` and `rounds`, with `remainingIssues` when it was rejected or `error` when a review's call failed").superRefine((review, ctx) => {
|
|
30762
|
+
const remaining = review.remainingIssues?.length ?? 0;
|
|
30763
|
+
if (review.verdict === "rejected" && remaining === 0) {
|
|
30764
|
+
ctx.addIssue({
|
|
30765
|
+
code: "custom",
|
|
30766
|
+
path: ["remainingIssues"],
|
|
30767
|
+
message: "a rejected review records the blocking issues its last round named"
|
|
30768
|
+
});
|
|
30769
|
+
}
|
|
30770
|
+
if (review.verdict === "rejected" && review.rounds < PLAN_REVIEW_MAX_ROUNDS) {
|
|
30771
|
+
ctx.addIssue({
|
|
30772
|
+
code: "custom",
|
|
30773
|
+
path: ["rounds"],
|
|
30774
|
+
message: `a review still rejecting after ${review.rounds} of ${PLAN_REVIEW_MAX_ROUNDS} rounds is revised and reviewed again, not recorded`
|
|
30775
|
+
});
|
|
30776
|
+
}
|
|
30777
|
+
if (review.verdict === "approved" && remaining > 0) {
|
|
30778
|
+
ctx.addIssue({
|
|
30779
|
+
code: "custom",
|
|
30780
|
+
path: ["remainingIssues"],
|
|
30781
|
+
message: "an approved review leaves no blocking issue standing"
|
|
30782
|
+
});
|
|
30783
|
+
}
|
|
30784
|
+
if (review.verdict === "failed" !== (review.error !== undefined)) {
|
|
30785
|
+
ctx.addIssue({
|
|
30786
|
+
code: "custom",
|
|
30787
|
+
path: ["error"],
|
|
30788
|
+
message: "a failed review records its call's error, and only a failed review does"
|
|
30789
|
+
});
|
|
30790
|
+
}
|
|
30791
|
+
});
|
|
30733
30792
|
var planWriteSchema = planSchema.extend({
|
|
30734
30793
|
requiredSkills: exports_external.object({
|
|
30735
30794
|
implement: nonEmptySkillList,
|
|
30736
30795
|
test: nonEmptySkillList,
|
|
30737
30796
|
review: nonEmptySkillList
|
|
30738
|
-
}).passthrough()
|
|
30797
|
+
}).passthrough(),
|
|
30798
|
+
gapAnalysis: gapAnalysisWriteSchema,
|
|
30799
|
+
planReview: planReviewWriteSchema
|
|
30739
30800
|
});
|
|
30740
30801
|
var phaseHandoffSchema = exports_external.discriminatedUnion("phase", [
|
|
30741
30802
|
architectSchema,
|
|
@@ -33611,7 +33672,7 @@ import { logger } from "@oh-my-pi/pi-utils";
|
|
|
33611
33672
|
// package.json
|
|
33612
33673
|
var package_default = {
|
|
33613
33674
|
name: "@sjawhar/pi-legion-envoy",
|
|
33614
|
-
version: "5.
|
|
33675
|
+
version: "5.29.0",
|
|
33615
33676
|
type: "module",
|
|
33616
33677
|
omp: {
|
|
33617
33678
|
extensions: [
|