@hilbras/omninode 2.0.0-alpha.10 → 2.0.0-alpha.11
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 +8 -1
- package/dist/cli/index.js +162 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +143 -10
- package/dist/index.js +423 -317
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ existing intelligence; it does not try to become another model.
|
|
|
18
18
|
|
|
19
19
|
## Status
|
|
20
20
|
|
|
21
|
-
**v2.0.0-alpha.
|
|
21
|
+
**v2.0.0-alpha.11 — v2 Phase 11: Planner v2**
|
|
22
22
|
(the reliability & interoperability line: architecture → execution →
|
|
23
23
|
protocol → adapters → pipelines → providers → OmniHilbras → memory → reports) (the v2
|
|
24
24
|
roadmap is [docs/ROADMAP_V2.md](docs/ROADMAP_V2.md); the v1 plan is complete:
|
|
@@ -31,6 +31,13 @@ for the plan and [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design).
|
|
|
31
31
|
|
|
32
32
|
### What's new in v2 (so far)
|
|
33
33
|
|
|
34
|
+
- **Phase 11 — Planner v2**: the planner now receives the full §15 input —
|
|
35
|
+
task, project context, agent reports, **aggregated findings (consensus and
|
|
36
|
+
conflicts included)**, memory and **constraints** (settable per pipeline
|
|
37
|
+
step). Plans carry an explicit goal, every generated plan is **schema
|
|
38
|
+
validated**, invalid output produces a **structured error** or falls back to
|
|
39
|
+
heuristic planning, and a guard test proves the planner module depends on no
|
|
40
|
+
specific provider.
|
|
34
41
|
- **Phase 10 — Aggregation Improvements**: when agents disagree,
|
|
35
42
|
OmniNode now says so instead of flattening the answer — **conflict
|
|
36
43
|
detection** preserves every position (severity spread, divergent
|
package/dist/cli/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { realpathSync } from "fs";
|
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/version.ts
|
|
9
|
-
var OMNINODE_VERSION = "2.0.0-alpha.
|
|
9
|
+
var OMNINODE_VERSION = "2.0.0-alpha.11";
|
|
10
10
|
|
|
11
11
|
// src/errors/index.ts
|
|
12
12
|
var OmniNodeError = class extends Error {
|
|
@@ -109,7 +109,9 @@ var pipelineStepConfigSchema = z.object({
|
|
|
109
109
|
model: z.string().optional(),
|
|
110
110
|
depends_on: z.array(z.string()).optional(),
|
|
111
111
|
retries: z.number().int().min(0).max(10).optional(),
|
|
112
|
-
condition: z.enum(["always", "on-success", "on-failure"]).optional()
|
|
112
|
+
condition: z.enum(["always", "on-success", "on-failure"]).optional(),
|
|
113
|
+
/** Constraints passed to the planner for plan steps (§15). */
|
|
114
|
+
constraints: z.array(z.string()).optional()
|
|
113
115
|
}).strict();
|
|
114
116
|
var pipelineConfigSchema = z.object({
|
|
115
117
|
id: z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*$/, "pipeline id must be kebab-case"),
|
|
@@ -239,7 +241,8 @@ function toPipelineDefinition(raw) {
|
|
|
239
241
|
model: step.model,
|
|
240
242
|
dependsOn: step.depends_on,
|
|
241
243
|
retries: step.retries,
|
|
242
|
-
condition: step.condition
|
|
244
|
+
condition: step.condition,
|
|
245
|
+
constraints: step.constraints
|
|
243
246
|
}))
|
|
244
247
|
};
|
|
245
248
|
}
|
|
@@ -3532,19 +3535,32 @@ var HeuristicPlanner = class {
|
|
|
3532
3535
|
name = "heuristic";
|
|
3533
3536
|
async plan(request) {
|
|
3534
3537
|
const steps = [];
|
|
3535
|
-
const findings = request.reports.flatMap(
|
|
3536
|
-
(report) => report.findings.map((finding) => ({ finding, agent: report.agent }))
|
|
3537
|
-
);
|
|
3538
3538
|
const recommendations = dedupe(request.reports.flatMap((r) => r.recommendations));
|
|
3539
|
-
for (const
|
|
3539
|
+
for (const text of recommendations) {
|
|
3540
3540
|
steps.push({
|
|
3541
3541
|
id: `step-${steps.length + 1}`,
|
|
3542
3542
|
title: truncate5(text, 120),
|
|
3543
3543
|
order: steps.length + 1,
|
|
3544
|
-
...
|
|
3544
|
+
...steps.length > 0 ? { dependsOn: [`step-${steps.length}`] } : {}
|
|
3545
3545
|
});
|
|
3546
3546
|
}
|
|
3547
|
-
const
|
|
3547
|
+
const contributed = request.aggregated ? request.aggregated.findings.map((finding) => ({
|
|
3548
|
+
finding: {
|
|
3549
|
+
id: `agg-${slug(finding.title)}`,
|
|
3550
|
+
title: finding.title,
|
|
3551
|
+
detail: finding.details[0] ?? finding.title,
|
|
3552
|
+
...finding.severity ? { severity: finding.severity } : {},
|
|
3553
|
+
...finding.recommendations && finding.recommendations.length > 0 ? { recommendation: finding.recommendations[0] } : {}
|
|
3554
|
+
},
|
|
3555
|
+
agent: finding.sources.map((s) => s.agent).join("+")
|
|
3556
|
+
})) : request.reports.flatMap(
|
|
3557
|
+
(report) => report.findings.map((finding) => ({ finding, agent: report.agent }))
|
|
3558
|
+
);
|
|
3559
|
+
const significant = contributed.filter(
|
|
3560
|
+
({ finding }) => finding.severity ? SEVERITY_RANK2[finding.severity] >= SEVERITY_RANK2.high : false
|
|
3561
|
+
).sort(
|
|
3562
|
+
(a, b) => SEVERITY_RANK2[b.finding.severity ?? "info"] - SEVERITY_RANK2[a.finding.severity ?? "info"]
|
|
3563
|
+
);
|
|
3548
3564
|
for (const { finding } of significant) {
|
|
3549
3565
|
steps.push(remediationStep(finding, steps.length + 1));
|
|
3550
3566
|
}
|
|
@@ -3557,12 +3573,20 @@ var HeuristicPlanner = class {
|
|
|
3557
3573
|
});
|
|
3558
3574
|
}
|
|
3559
3575
|
const risks = significant.filter(({ finding }) => finding.severity === "critical").map(({ finding }) => `Critical finding unaddressed until its step completes: ${finding.title}`);
|
|
3576
|
+
const conflicts = request.aggregated?.conflicts ?? [];
|
|
3577
|
+
if (conflicts.length > 0) {
|
|
3578
|
+
risks.push(
|
|
3579
|
+
`${conflicts.length} unresolved agent disagreement(s): ${conflicts.map((c) => c.findingTitle).join("; ")}`
|
|
3580
|
+
);
|
|
3581
|
+
}
|
|
3560
3582
|
return {
|
|
3561
3583
|
id: `plan-${Date.now().toString(36)}-${randomBytes3(3).toString("hex")}`,
|
|
3562
3584
|
objective: request.objective,
|
|
3585
|
+
goal: request.aggregated?.title ?? truncate5(request.objective, 120),
|
|
3563
3586
|
summary: `Derived from ${request.reports.length} report(s): ${recommendations.length} recommendation step(s), ${significant.length} remediation step(s).`,
|
|
3564
3587
|
steps,
|
|
3565
3588
|
...risks.length > 0 ? { risks } : {},
|
|
3589
|
+
...request.constraints !== void 0 && request.constraints.length > 0 ? { constraints: request.constraints } : {},
|
|
3566
3590
|
generatedBy: "heuristic",
|
|
3567
3591
|
...request.taskId !== void 0 ? { taskId: request.taskId } : {},
|
|
3568
3592
|
...request.pipelineRunId !== void 0 ? { pipelineRunId: request.pipelineRunId } : {},
|
|
@@ -3577,24 +3601,76 @@ function remediationStep(finding, order) {
|
|
|
3577
3601
|
description: finding.detail,
|
|
3578
3602
|
order,
|
|
3579
3603
|
dependsOn: order > 1 ? [`step-${order - 1}`] : [],
|
|
3580
|
-
sourceFindings: [finding.id]
|
|
3604
|
+
sourceFindings: [finding.id],
|
|
3605
|
+
...finding.recommendation ? { recommendation: finding.recommendation } : {}
|
|
3581
3606
|
};
|
|
3582
3607
|
}
|
|
3583
3608
|
function dedupe(texts) {
|
|
3584
3609
|
return [...new Set(texts.map((t) => t.trim()).filter((t) => t.length > 0))];
|
|
3585
3610
|
}
|
|
3611
|
+
function slug(text) {
|
|
3612
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
3613
|
+
}
|
|
3586
3614
|
function truncate5(text, max) {
|
|
3587
3615
|
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
3588
3616
|
}
|
|
3589
3617
|
|
|
3590
3618
|
// src/planner/model.ts
|
|
3591
3619
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
3620
|
+
|
|
3621
|
+
// src/planner/schema.ts
|
|
3592
3622
|
import { z as z3 } from "zod";
|
|
3623
|
+
var planStepSchema = z3.object({
|
|
3624
|
+
id: z3.string().min(1).optional(),
|
|
3625
|
+
title: z3.string().min(1),
|
|
3626
|
+
description: z3.string().optional(),
|
|
3627
|
+
order: z3.number().int().optional(),
|
|
3628
|
+
targets: z3.array(z3.string()).optional(),
|
|
3629
|
+
acceptance_criteria: z3.array(z3.string()).optional(),
|
|
3630
|
+
depends_on: z3.array(z3.string()).optional(),
|
|
3631
|
+
source_findings: z3.array(z3.string()).optional()
|
|
3632
|
+
});
|
|
3633
|
+
var planJsonSchema = z3.object({
|
|
3634
|
+
goal: z3.string().min(1),
|
|
3635
|
+
summary: z3.string().min(1),
|
|
3636
|
+
steps: z3.array(planStepSchema).min(1),
|
|
3637
|
+
risks: z3.array(z3.string()).optional(),
|
|
3638
|
+
notes: z3.array(z3.string()).optional()
|
|
3639
|
+
});
|
|
3640
|
+
function validatePlan(plan) {
|
|
3641
|
+
const issues = [];
|
|
3642
|
+
const stepIds = /* @__PURE__ */ new Set();
|
|
3643
|
+
for (const [index, step] of plan.steps.entries()) {
|
|
3644
|
+
if (stepIds.has(step.id)) {
|
|
3645
|
+
issues.push({ path: `steps.${index}.id`, message: `duplicate step id "${step.id}"` });
|
|
3646
|
+
}
|
|
3647
|
+
stepIds.add(step.id);
|
|
3648
|
+
if (!step.title || step.title.trim().length === 0) {
|
|
3649
|
+
issues.push({ path: `steps.${index}.title`, message: "title must not be empty" });
|
|
3650
|
+
}
|
|
3651
|
+
for (const dep of step.dependsOn ?? []) {
|
|
3652
|
+
if (!stepIds.has(dep) && !plan.steps.some((s) => s.id === dep)) {
|
|
3653
|
+
issues.push({ path: `steps.${index}.dependsOn`, message: `unknown step dependency "${dep}"` });
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
if (plan.steps.length === 0) {
|
|
3658
|
+
issues.push({ path: "steps", message: "a plan needs at least one step" });
|
|
3659
|
+
}
|
|
3660
|
+
if (!plan.summary || plan.summary.trim().length === 0) {
|
|
3661
|
+
issues.push({ path: "summary", message: "summary must not be empty" });
|
|
3662
|
+
}
|
|
3663
|
+
return issues.length > 0 ? { valid: false, issues, reason: `plan failed validation (${issues.length} issue(s))` } : { valid: true, plan };
|
|
3664
|
+
}
|
|
3593
3665
|
|
|
3594
3666
|
// src/planner/context.ts
|
|
3595
3667
|
function buildPlannerContext(request) {
|
|
3596
|
-
const parts = [`#
|
|
3668
|
+
const parts = [`# Task
|
|
3597
3669
|
${request.objective}`];
|
|
3670
|
+
if (request.projectContext) {
|
|
3671
|
+
parts.push(`# Project context
|
|
3672
|
+
${request.projectContext}`);
|
|
3673
|
+
}
|
|
3598
3674
|
if (request.role) {
|
|
3599
3675
|
const roleLines = [`# Role
|
|
3600
3676
|
${request.role.name} (${request.role.id})`];
|
|
@@ -3614,7 +3690,7 @@ ${request.role.name} (${request.role.id})`];
|
|
|
3614
3690
|
)
|
|
3615
3691
|
);
|
|
3616
3692
|
parts.push(
|
|
3617
|
-
`#
|
|
3693
|
+
`# Agent reports (${request.reports.length} by ${agents})
|
|
3618
3694
|
` + (findingLines.length > 0 ? findingLines.join("\n") : "(no findings reported)")
|
|
3619
3695
|
);
|
|
3620
3696
|
const recommendationLines = request.reports.flatMap(
|
|
@@ -3624,9 +3700,20 @@ ${request.role.name} (${request.role.id})`];
|
|
|
3624
3700
|
parts.push(`# Recommendations
|
|
3625
3701
|
${recommendationLines.join("\n")}`);
|
|
3626
3702
|
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3703
|
+
}
|
|
3704
|
+
if (request.aggregated) {
|
|
3705
|
+
const aggregatedLines = [
|
|
3706
|
+
`- findings: ${request.aggregated.findings.length} (agreements: ${request.aggregated.agreements.length}, conflicts: ${request.aggregated.conflicts.length})`,
|
|
3707
|
+
...request.aggregated.findings.map(
|
|
3708
|
+
(finding) => `- [${finding.severity ?? "info"}] ${finding.title} (x${finding.occurrences})`
|
|
3709
|
+
),
|
|
3710
|
+
// Conflicts stay visible to the planner — it must plan around disagreement.
|
|
3711
|
+
...request.aggregated.conflicts.map(
|
|
3712
|
+
(conflict) => `- CONFLICT (${conflict.type}) on "${conflict.findingTitle}": ${conflict.note}`
|
|
3713
|
+
)
|
|
3714
|
+
];
|
|
3715
|
+
parts.push(`# Aggregated findings
|
|
3716
|
+
${aggregatedLines.join("\n")}`);
|
|
3630
3717
|
}
|
|
3631
3718
|
if (request.memory && request.memory.length > 0) {
|
|
3632
3719
|
parts.push(
|
|
@@ -3634,7 +3721,11 @@ ${summaryLines.join("\n")}`);
|
|
|
3634
3721
|
` + request.memory.map((entry2) => `- [${entry2.scope}] ${entry2.content}`).join("\n")
|
|
3635
3722
|
);
|
|
3636
3723
|
}
|
|
3637
|
-
if (request.
|
|
3724
|
+
if (request.constraints && request.constraints.length > 0) {
|
|
3725
|
+
parts.push(`# Constraints
|
|
3726
|
+
${request.constraints.map((c) => `- ${c}`).join("\n")}`);
|
|
3727
|
+
}
|
|
3728
|
+
if (request.context) {
|
|
3638
3729
|
parts.push(`# Research context
|
|
3639
3730
|
${request.context}`);
|
|
3640
3731
|
}
|
|
@@ -3642,22 +3733,6 @@ ${request.context}`);
|
|
|
3642
3733
|
}
|
|
3643
3734
|
|
|
3644
3735
|
// src/planner/model.ts
|
|
3645
|
-
var planStepJsonSchema = z3.object({
|
|
3646
|
-
id: z3.string().optional(),
|
|
3647
|
-
title: z3.string().min(1),
|
|
3648
|
-
description: z3.string().optional(),
|
|
3649
|
-
order: z3.number().int().optional(),
|
|
3650
|
-
targets: z3.array(z3.string()).optional(),
|
|
3651
|
-
acceptance_criteria: z3.array(z3.string()).optional(),
|
|
3652
|
-
depends_on: z3.array(z3.string()).optional(),
|
|
3653
|
-
source_findings: z3.array(z3.string()).optional()
|
|
3654
|
-
}).strict();
|
|
3655
|
-
var planJsonSchema = z3.object({
|
|
3656
|
-
summary: z3.string().min(1),
|
|
3657
|
-
steps: z3.array(planStepJsonSchema).min(1),
|
|
3658
|
-
risks: z3.array(z3.string()).optional(),
|
|
3659
|
-
notes: z3.array(z3.string()).optional()
|
|
3660
|
-
}).strict();
|
|
3661
3736
|
var ModelPlanner = class {
|
|
3662
3737
|
constructor(options) {
|
|
3663
3738
|
this.options = options;
|
|
@@ -3671,7 +3746,7 @@ var ModelPlanner = class {
|
|
|
3671
3746
|
const messages = [
|
|
3672
3747
|
{
|
|
3673
3748
|
role: "system",
|
|
3674
|
-
content: 'You are the OmniNode planner. Given the objective and the combined research context, produce a final analysis and a prioritized, actionable implementation plan. Respond with JSON ONLY (no prose, no code fences) matching exactly this shape: {"summary": string, "steps": [{"id": string, "title": string, "description": string, "order": number, "targets": string[], "acceptance_criteria": string[], "source_findings": string[]}], "risks": string[], "notes": string[]}. ' + (this.options.instruction ?? "")
|
|
3749
|
+
content: 'You are the OmniNode planner. Given the objective and the combined research context, produce a final analysis and a prioritized, actionable implementation plan. Respond with JSON ONLY (no prose, no code fences) matching exactly this shape: {"goal": string, "summary": string, "steps": [{"id": string, "title": string, "description": string, "order": number, "targets": string[], "acceptance_criteria": string[], "source_findings": string[]}], "risks": string[], "notes": string[]}. ' + (this.options.instruction ?? "")
|
|
3675
3750
|
},
|
|
3676
3751
|
{ role: "user", content: context }
|
|
3677
3752
|
];
|
|
@@ -3682,60 +3757,86 @@ var ModelPlanner = class {
|
|
|
3682
3757
|
return this.degrade(request, `planner model call failed: ${describe(error)}`);
|
|
3683
3758
|
}
|
|
3684
3759
|
const parsed = parsePlanJson(responseText);
|
|
3685
|
-
if (!parsed) {
|
|
3686
|
-
return this.degrade(request,
|
|
3760
|
+
if (!parsed.ok) {
|
|
3761
|
+
return this.degrade(request, `planner model output rejected: ${parsed.reason}`, parsed.issues);
|
|
3687
3762
|
}
|
|
3688
3763
|
const plan = {
|
|
3689
3764
|
id: `plan-${Date.now().toString(36)}-${randomBytes4(3).toString("hex")}`,
|
|
3690
3765
|
objective: request.objective,
|
|
3766
|
+
goal: parsed.goal,
|
|
3691
3767
|
summary: parsed.summary,
|
|
3692
3768
|
steps: parsed.steps,
|
|
3693
3769
|
...parsed.risks !== void 0 ? { risks: parsed.risks } : {},
|
|
3694
3770
|
...parsed.notes !== void 0 ? { notes: parsed.notes } : {},
|
|
3771
|
+
...request.constraints !== void 0 && request.constraints.length > 0 ? { constraints: request.constraints } : {},
|
|
3695
3772
|
generatedBy: `model:${this.options.model}`,
|
|
3696
3773
|
model: this.options.model,
|
|
3697
3774
|
...request.taskId !== void 0 ? { taskId: request.taskId } : {},
|
|
3698
3775
|
...request.pipelineRunId !== void 0 ? { pipelineRunId: request.pipelineRunId } : {},
|
|
3699
3776
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3700
3777
|
};
|
|
3701
|
-
|
|
3778
|
+
const validation = validatePlan(plan);
|
|
3779
|
+
if (!validation.valid) {
|
|
3780
|
+
return this.degrade(request, `generated plan rejected: ${validation.reason}`, validation.issues);
|
|
3781
|
+
}
|
|
3782
|
+
return validation.plan;
|
|
3702
3783
|
}
|
|
3703
|
-
async degrade(request, reason) {
|
|
3784
|
+
async degrade(request, reason, issues = []) {
|
|
3704
3785
|
if (this.options.fallback) {
|
|
3705
3786
|
this.log.warn(`${reason} \u2014 using the heuristic fallback planner.`);
|
|
3706
3787
|
return this.options.fallback.plan(request);
|
|
3707
3788
|
}
|
|
3708
|
-
throw new PlannerError("
|
|
3789
|
+
throw new PlannerError("PLAN_INVALID", `Planner failed: ${reason}.`, {
|
|
3790
|
+
details: { reason, issues }
|
|
3791
|
+
});
|
|
3709
3792
|
}
|
|
3710
3793
|
};
|
|
3711
3794
|
function parsePlanJson(text) {
|
|
3712
3795
|
const unfenced = text.replace(/```(?:json)?/gi, "");
|
|
3713
3796
|
const start = unfenced.indexOf("{");
|
|
3714
3797
|
const end = unfenced.lastIndexOf("}");
|
|
3715
|
-
if (start < 0 || end <= start)
|
|
3798
|
+
if (start < 0 || end <= start) {
|
|
3799
|
+
return { ok: false, reason: "planner output contained no JSON object", issues: [] };
|
|
3800
|
+
}
|
|
3801
|
+
let json;
|
|
3716
3802
|
try {
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
if (!parsed.success) return void 0;
|
|
3720
|
-
const steps = parsed.data.steps.map((step, index) => ({
|
|
3721
|
-
id: step.id ?? `step-${index + 1}`,
|
|
3722
|
-
title: step.title,
|
|
3723
|
-
description: step.description,
|
|
3724
|
-
order: step.order ?? index + 1,
|
|
3725
|
-
targets: step.targets,
|
|
3726
|
-
acceptanceCriteria: step.acceptance_criteria,
|
|
3727
|
-
dependsOn: step.depends_on,
|
|
3728
|
-
sourceFindings: step.source_findings
|
|
3729
|
-
}));
|
|
3803
|
+
json = JSON.parse(unfenced.slice(start, end + 1));
|
|
3804
|
+
} catch (error) {
|
|
3730
3805
|
return {
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
notes: parsed.data.notes
|
|
3806
|
+
ok: false,
|
|
3807
|
+
reason: `planner output was not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
3808
|
+
issues: []
|
|
3735
3809
|
};
|
|
3736
|
-
} catch {
|
|
3737
|
-
return void 0;
|
|
3738
3810
|
}
|
|
3811
|
+
const parsed = planJsonSchema.safeParse(json);
|
|
3812
|
+
if (!parsed.success) {
|
|
3813
|
+
return {
|
|
3814
|
+
ok: false,
|
|
3815
|
+
reason: "planner output did not match the plan schema",
|
|
3816
|
+
issues: parsed.error.issues.map((issue) => ({
|
|
3817
|
+
path: issue.path.join(".") || "(root)",
|
|
3818
|
+
message: issue.message
|
|
3819
|
+
}))
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
const steps = parsed.data.steps.map((step, index) => ({
|
|
3823
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3824
|
+
title: step.title,
|
|
3825
|
+
description: step.description,
|
|
3826
|
+
order: step.order ?? index + 1,
|
|
3827
|
+
targets: step.targets,
|
|
3828
|
+
acceptanceCriteria: step.acceptance_criteria,
|
|
3829
|
+
dependsOn: step.depends_on,
|
|
3830
|
+
sourceFindings: step.source_findings
|
|
3831
|
+
})).sort((a, b) => a.order - b.order);
|
|
3832
|
+
return {
|
|
3833
|
+
ok: true,
|
|
3834
|
+
goal: parsed.data.goal,
|
|
3835
|
+
summary: parsed.data.summary,
|
|
3836
|
+
steps,
|
|
3837
|
+
risks: parsed.data.risks,
|
|
3838
|
+
notes: parsed.data.notes
|
|
3839
|
+
};
|
|
3739
3840
|
}
|
|
3740
3841
|
function describe(error) {
|
|
3741
3842
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4173,11 +4274,14 @@ ${contribution}`);
|
|
|
4173
4274
|
};
|
|
4174
4275
|
}
|
|
4175
4276
|
async runPlan(step, ctx) {
|
|
4277
|
+
const aggregated = ctx.reports.length > 0 ? aggregateReports(ctx.reports) : void 0;
|
|
4176
4278
|
const request = {
|
|
4177
4279
|
objective: ctx.objective,
|
|
4178
4280
|
reports: ctx.reports,
|
|
4281
|
+
...aggregated !== void 0 ? { aggregated } : {},
|
|
4179
4282
|
...ctx.combinedContext.length > 0 ? { context: ctx.combinedContext } : {},
|
|
4180
4283
|
...ctx.role ? { role: ctx.role } : {},
|
|
4284
|
+
...step.constraints !== void 0 && step.constraints.length > 0 ? { constraints: step.constraints } : {},
|
|
4181
4285
|
...ctx.pipelineRunId !== void 0 ? { pipelineRunId: ctx.pipelineRunId } : {}
|
|
4182
4286
|
};
|
|
4183
4287
|
let planner;
|