@llm-dev-ops/agentics-cli 1.6.5 → 1.6.7
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/deps/erp-database-map.d.ts +14 -1
- package/dist/deps/erp-database-map.d.ts.map +1 -1
- package/dist/deps/erp-database-map.js +20 -14
- package/dist/deps/erp-database-map.js.map +1 -1
- package/dist/pipeline/phase2/phases/adr-generator.d.ts.map +1 -1
- package/dist/pipeline/phase2/phases/adr-generator.js +8 -2
- package/dist/pipeline/phase2/phases/adr-generator.js.map +1 -1
- package/dist/pipeline/phase2/phases/tech-stack-detector.d.ts.map +1 -1
- package/dist/pipeline/phase2/phases/tech-stack-detector.js +30 -19
- package/dist/pipeline/phase2/phases/tech-stack-detector.js.map +1 -1
- package/dist/pipeline/phase4/phases/erp-target-resolver.d.ts.map +1 -1
- package/dist/pipeline/phase4/phases/erp-target-resolver.js +5 -2
- package/dist/pipeline/phase4/phases/erp-target-resolver.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +351 -306
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/package.json +1 -1
|
@@ -133,144 +133,201 @@ function extractSuccessProbability(simData) {
|
|
|
133
133
|
// Enterprise projects always carry residual risk, and showing 100% destroys credibility.
|
|
134
134
|
return Math.min(prob, 0.88);
|
|
135
135
|
}
|
|
136
|
+
function extractFinancials(simData, platformResults) {
|
|
137
|
+
const fm = (safeGet(simData, 'financial_model') ?? safeGet(simData, 'cost_model') ?? safeGet(simData, 'financials'));
|
|
138
|
+
const roiAgent = extractAgentData(platformResults, 'costops', 'roi');
|
|
139
|
+
const forecastAgent = extractAgentData(platformResults, 'costops', 'forecast');
|
|
140
|
+
const budget = safeString(simData, 'budget') || safeString(simData, 'investment') || safeString(simData, 'total_investment') || (fm ? safeString(fm, 'budget') || safeString(fm, 'total_investment') : '') || (roiAgent ? safeString(roiAgent, 'total_cost') || safeString(roiAgent, 'estimated_cost') : '');
|
|
141
|
+
const roi = safeString(simData, 'roi') || safeString(simData, 'expected_roi') || (fm ? safeString(fm, 'roi') : '') || (roiAgent ? safeString(roiAgent, 'roi') || safeString(roiAgent, 'expected_roi') : '');
|
|
142
|
+
const npv = safeString(simData, 'npv') || safeString(simData, 'net_present_value') || (fm ? safeString(fm, 'npv') || safeString(fm, 'net_present_value') : '') || (forecastAgent ? safeString(forecastAgent, 'npv') : '');
|
|
143
|
+
const payback = safeString(simData, 'payback_period') || safeString(simData, 'payback') || safeString(simData, 'roi_timeline') || (fm ? safeString(fm, 'payback_period') || safeString(fm, 'payback') : '') || (roiAgent ? safeString(roiAgent, 'payback_period') || safeString(roiAgent, 'payback') : '');
|
|
144
|
+
const revenue = safeString(simData, 'projected_revenue') || safeString(simData, 'revenue_impact') || safeString(simData, 'annual_value') || (fm ? safeString(fm, 'projected_revenue') : '');
|
|
145
|
+
const costSavings = safeString(simData, 'cost_savings') || safeString(simData, 'cost_reduction') || safeString(simData, 'savings') || (fm ? safeString(fm, 'cost_savings') : '');
|
|
146
|
+
return { budget, roi, npv, payback, revenue, costSavings, hasData: !!(budget || roi || npv || payback || revenue || costSavings) };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* ADR-PIPELINE-024: Generate domain-appropriate risks from query context.
|
|
150
|
+
* Every enterprise project has risks. Never return an empty list.
|
|
151
|
+
*/
|
|
152
|
+
function generateDomainRisks(query, extracted) {
|
|
153
|
+
const risks = [];
|
|
154
|
+
const q = query.toLowerCase();
|
|
155
|
+
const systems = extracted.systems;
|
|
156
|
+
const primarySystem = systems[0] ?? 'enterprise platform';
|
|
157
|
+
// Every project has these
|
|
158
|
+
risks.push({
|
|
159
|
+
risk: `Data quality and completeness in ${primarySystem} may not meet analytical requirements`,
|
|
160
|
+
category: 'Data', likelihood: 'High', impact: 'Medium', score: 6,
|
|
161
|
+
mitigation: 'Data profiling during discovery phase; validation layer with quarantine for invalid records',
|
|
162
|
+
});
|
|
163
|
+
risks.push({
|
|
164
|
+
risk: `${primarySystem} API integration complexity — rate limits, schema changes, authentication`,
|
|
165
|
+
category: 'Technical', likelihood: 'Medium', impact: 'High', score: 6,
|
|
166
|
+
mitigation: `Technical spike to validate ${primarySystem} API capabilities before full commitment`,
|
|
167
|
+
});
|
|
168
|
+
risks.push({
|
|
169
|
+
risk: 'Scope creep beyond initial prototype boundaries',
|
|
170
|
+
category: 'Project', likelihood: 'High', impact: 'Medium', score: 6,
|
|
171
|
+
mitigation: 'Fixed scope contract with explicit phase gates; changes require stakeholder re-approval',
|
|
172
|
+
});
|
|
173
|
+
// Size-dependent risks
|
|
174
|
+
if (/\b\d{2,6}\s*(?:employee|staff|people|worker|team member)/i.test(q)) {
|
|
175
|
+
risks.push({
|
|
176
|
+
risk: 'Change management across large workforce — adoption resistance and training burden',
|
|
177
|
+
category: 'Organizational', likelihood: 'Medium', impact: 'High', score: 6,
|
|
178
|
+
mitigation: 'Phased rollout starting with pilot group; champion network; training program before go-live',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// Multi-region risks
|
|
182
|
+
if (/(?:north america|europe|asia|global|multi.?region|across.*(?:region|countr|continent))/i.test(q)) {
|
|
183
|
+
risks.push({
|
|
184
|
+
risk: 'Regional regulatory variance — data residency, privacy, and compliance requirements differ by jurisdiction',
|
|
185
|
+
category: 'Regulatory', likelihood: 'Medium', impact: 'High', score: 6,
|
|
186
|
+
mitigation: 'Legal review per jurisdiction during discovery; configurable compliance rules per region',
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// Sustainability risks
|
|
190
|
+
if (/(?:emission|carbon|sustainab|environmental|energy|waste|esg)/i.test(q)) {
|
|
191
|
+
risks.push({
|
|
192
|
+
risk: 'Emissions factor accuracy — default factors may not match specific operational context',
|
|
193
|
+
category: 'Data', likelihood: 'Medium', impact: 'Medium', score: 4,
|
|
194
|
+
mitigation: 'Allow user-supplied factors with audit trail; flag calculations using default vs. measured values',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Financial risks
|
|
198
|
+
if (/(?:investment|budget|cost|roi|revenue|profitab)/i.test(q)) {
|
|
199
|
+
risks.push({
|
|
200
|
+
risk: 'Financial assumptions may not hold — market conditions, operational costs, or adoption rates may differ from projections',
|
|
201
|
+
category: 'Financial', likelihood: 'Medium', impact: 'Medium', score: 4,
|
|
202
|
+
mitigation: 'Sensitivity analysis on key assumptions; quarterly re-validation of financial model',
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// Always include vendor dependency
|
|
206
|
+
risks.push({
|
|
207
|
+
risk: 'Technology vendor dependency — platform availability, pricing changes, or API deprecation',
|
|
208
|
+
category: 'Technical', likelihood: 'Low', impact: 'High', score: 3,
|
|
209
|
+
mitigation: 'Ports-and-adapters architecture enables vendor swap; contractual SLA requirements',
|
|
210
|
+
});
|
|
211
|
+
return risks.sort((a, b) => b.score - a.score);
|
|
212
|
+
}
|
|
136
213
|
// ============================================================================
|
|
137
|
-
// Executive Summary Renderer
|
|
214
|
+
// Executive Summary Renderer (ADR-PIPELINE-024: Pyramid Principle)
|
|
138
215
|
// ============================================================================
|
|
139
216
|
export function renderExecutiveSummary(query, simulationResult, platformResults) {
|
|
140
217
|
const now = new Date().toISOString();
|
|
141
|
-
const execSummaryAgent = platformResults.find(r => r.agent === 'executive-summary');
|
|
142
|
-
const riskAgent = platformResults.find(r => r.agent === 'risk-score');
|
|
143
|
-
const decisionAgent = platformResults.find(r => r.agent === 'decision-memo');
|
|
144
|
-
// Extract simulation outcome
|
|
145
218
|
const simPayload = extractSignalPayload(simulationResult);
|
|
146
219
|
const simData = simPayload.data ?? {};
|
|
147
220
|
const successProb = extractSuccessProbability(simData);
|
|
148
|
-
const timeline = safeString(simData, 'timeline_estimate') || safeString(simData, 'timeline');
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
// Determine confidence level
|
|
155
|
-
let confidence = 'LOW';
|
|
156
|
-
if (successProb >= 0.9)
|
|
157
|
-
confidence = 'HIGH';
|
|
158
|
-
else if (successProb >= 0.7)
|
|
159
|
-
confidence = 'MEDIUM';
|
|
160
|
-
// Determine recommendation
|
|
221
|
+
const timeline = safeString(simData, 'timeline_estimate') || safeString(simData, 'timeline') || '12-18 weeks';
|
|
222
|
+
const problemStatement = distillProblemStatement(query);
|
|
223
|
+
const extracted = extractScenarioFromQuery(query);
|
|
224
|
+
const fin = extractFinancials(simData, platformResults);
|
|
225
|
+
const risks = generateDomainRisks(query, extracted);
|
|
226
|
+
const primarySystem = extracted.systems[0] ?? 'the target platform';
|
|
161
227
|
let recommendation = 'DEFER';
|
|
162
|
-
|
|
228
|
+
let recDetail = 'Further analysis recommended before committing resources.';
|
|
229
|
+
if (successProb >= 0.9) {
|
|
163
230
|
recommendation = 'PROCEED';
|
|
164
|
-
|
|
231
|
+
recDetail = `Proceed with full implementation targeting ${primarySystem} integration.`;
|
|
232
|
+
}
|
|
233
|
+
else if (successProb >= 0.7) {
|
|
165
234
|
recommendation = 'CONDITIONAL PROCEED';
|
|
166
|
-
|
|
167
|
-
|
|
235
|
+
recDetail = `Proceed with a scoped pilot to validate core assumptions before full commitment.`;
|
|
236
|
+
}
|
|
237
|
+
// ADR-PIPELINE-024: Pyramid Principle — lead with the answer
|
|
168
238
|
const lines = [
|
|
169
239
|
'# Executive Summary',
|
|
170
240
|
'',
|
|
171
241
|
`**Date:** ${now}`,
|
|
172
|
-
`**Assessment:** ${problemStatement}`,
|
|
173
|
-
`**Confidence Level:** ${confidence}`,
|
|
174
|
-
`**Recommendation:** ${recommendation}`,
|
|
175
242
|
'',
|
|
176
243
|
'---',
|
|
177
244
|
'',
|
|
178
|
-
'##
|
|
179
|
-
'',
|
|
180
|
-
`This enterprise feasibility analysis evaluates the proposed initiative: **${problemStatement}**.`,
|
|
181
|
-
'',
|
|
182
|
-
`| Metric | Value |`,
|
|
183
|
-
`|--------|-------|`,
|
|
184
|
-
`| Success Probability | ${(successProb * 100).toFixed(0)}% |`,
|
|
185
|
-
`| Estimated Timeline | ${timeline || '12-18 weeks (to be refined)'} |`,
|
|
186
|
-
`| Confidence Level | ${confidence} |`,
|
|
245
|
+
'## Recommendation',
|
|
187
246
|
'',
|
|
247
|
+
`**${recommendation}** — ${recDetail}`,
|
|
188
248
|
];
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
249
|
+
if (fin.hasData) {
|
|
250
|
+
const impactParts = [];
|
|
251
|
+
if (fin.budget)
|
|
252
|
+
impactParts.push(`${fin.budget} investment`);
|
|
253
|
+
if (fin.payback)
|
|
254
|
+
impactParts.push(`${fin.payback} payback`);
|
|
255
|
+
if (fin.npv)
|
|
256
|
+
impactParts.push(`${fin.npv} 5-year NPV`);
|
|
257
|
+
if (impactParts.length > 0) {
|
|
258
|
+
lines.push(`Projected impact: ${impactParts.join(', ')}.`);
|
|
199
259
|
}
|
|
200
|
-
lines.push('');
|
|
201
260
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
261
|
+
lines.push(`Success probability: ${(successProb * 100).toFixed(0)}% | Timeline: ${timeline}`, '');
|
|
262
|
+
// The Opportunity — cost of inaction
|
|
263
|
+
lines.push('## The Opportunity', '');
|
|
264
|
+
lines.push(`${problemStatement}. Current processes rely on manual review and periodic reporting, ` +
|
|
265
|
+
`limiting the organization's ability to act proactively. Without intervention, inefficiencies ` +
|
|
266
|
+
`compound as operational scale grows across ${extracted.stakeholders.length > 0 ? extracted.stakeholders.slice(0, 2).join(' and ') : 'multiple teams'} ` +
|
|
267
|
+
`and ${primarySystem} data volume increases.`, '');
|
|
268
|
+
// What We Found — key insights with numbers
|
|
269
|
+
lines.push('## Key Findings', '');
|
|
270
|
+
const insights = [];
|
|
271
|
+
if (fin.roi)
|
|
272
|
+
insights.push(`Projected return on investment of ${fin.roi}`);
|
|
273
|
+
if (fin.costSavings)
|
|
274
|
+
insights.push(`Estimated cost savings of ${fin.costSavings}`);
|
|
275
|
+
if (fin.revenue)
|
|
276
|
+
insights.push(`Revenue impact potential of ${fin.revenue}`);
|
|
277
|
+
// Pull agent insights
|
|
278
|
+
const execAgent = extractAgentData(platformResults, 'platform', 'executive-summary');
|
|
279
|
+
if (execAgent) {
|
|
280
|
+
const findings = safeArray(execAgent, 'findings').concat(safeArray(execAgent, 'key_findings'));
|
|
281
|
+
for (const f of findings.slice(0, 3)) {
|
|
282
|
+
insights.push(typeof f === 'string' ? f : safeString(f, 'description') || safeString(f, 'finding') || String(f));
|
|
206
283
|
}
|
|
207
|
-
lines.push('');
|
|
208
284
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (
|
|
213
|
-
lines.push(
|
|
214
|
-
const insights = synthesizeAgentInsights(execPayload.data, 'executive-summary');
|
|
215
|
-
lines.push(...insights);
|
|
216
|
-
lines.push('');
|
|
217
|
-
}
|
|
285
|
+
insights.push(`${primarySystem} integration is technically feasible with ${extracted.constraints.length > 0 ? 'identified compliance constraints manageable' : 'standard API integration patterns'}`);
|
|
286
|
+
insights.push('Human-in-the-loop governance preserves decision authority while accelerating analysis');
|
|
287
|
+
for (const insight of insights.slice(0, 6)) {
|
|
288
|
+
if (insight)
|
|
289
|
+
lines.push(`- ${insight}`);
|
|
218
290
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
lines.push(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const execFinModel = safeGet(simData, 'financial_model');
|
|
237
|
-
if (execBudget || execRoi || execNpv || execPayback || execFinModel || roiAgent || forecastAgent) {
|
|
238
|
-
lines.push('## Financial Overview', '');
|
|
239
|
-
if (execBudget)
|
|
240
|
-
lines.push(`- **Total Investment:** ${execBudget}`);
|
|
241
|
-
if (execRoi)
|
|
242
|
-
lines.push(`- **Expected ROI:** ${execRoi}`);
|
|
243
|
-
if (execNpv)
|
|
244
|
-
lines.push(`- **5-Year NPV:** ${execNpv}`);
|
|
245
|
-
if (execPayback)
|
|
246
|
-
lines.push(`- **Payback Period:** ${execPayback}`);
|
|
247
|
-
if (execFinModel) {
|
|
248
|
-
const fmRevenue = safeString(execFinModel, 'projected_revenue') || safeString(execFinModel, 'annual_value');
|
|
249
|
-
if (fmRevenue)
|
|
250
|
-
lines.push(`- **Projected Revenue:** ${fmRevenue}`);
|
|
251
|
-
}
|
|
252
|
-
if (roiAgent) {
|
|
253
|
-
const insights = synthesizeAgentInsights(roiAgent, 'costops-roi');
|
|
254
|
-
lines.push('', ...insights);
|
|
255
|
-
}
|
|
256
|
-
if (forecastAgent) {
|
|
257
|
-
const insights = synthesizeAgentInsights(forecastAgent, 'costops-forecast');
|
|
258
|
-
lines.push('', ...insights);
|
|
259
|
-
}
|
|
291
|
+
lines.push('');
|
|
292
|
+
// Financial Impact
|
|
293
|
+
if (fin.hasData) {
|
|
294
|
+
lines.push('## Financial Impact', '');
|
|
295
|
+
lines.push('| Metric | Value |', '|--------|-------|');
|
|
296
|
+
if (fin.budget)
|
|
297
|
+
lines.push(`| Total Investment | ${fin.budget} |`);
|
|
298
|
+
if (fin.roi)
|
|
299
|
+
lines.push(`| Expected ROI | ${fin.roi} |`);
|
|
300
|
+
if (fin.npv)
|
|
301
|
+
lines.push(`| 5-Year NPV | ${fin.npv} |`);
|
|
302
|
+
if (fin.payback)
|
|
303
|
+
lines.push(`| Payback Period | ${fin.payback} |`);
|
|
304
|
+
if (fin.revenue)
|
|
305
|
+
lines.push(`| Revenue Impact | ${fin.revenue} |`);
|
|
306
|
+
if (fin.costSavings)
|
|
307
|
+
lines.push(`| Cost Savings | ${fin.costSavings} |`);
|
|
260
308
|
lines.push('');
|
|
261
309
|
}
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
lines.push('---', '');
|
|
271
|
-
if (execSources.length > 0) {
|
|
272
|
-
lines.push(`*Sources: ${execSources.join(', ')}*`);
|
|
310
|
+
// Risk Profile — never empty
|
|
311
|
+
lines.push('## Risk Profile', '');
|
|
312
|
+
const topRisks = risks.slice(0, 3);
|
|
313
|
+
const maxScore = topRisks[0]?.score ?? 0;
|
|
314
|
+
const riskLevel = maxScore >= 6 ? 'MEDIUM' : maxScore >= 3 ? 'LOW-MEDIUM' : 'LOW';
|
|
315
|
+
lines.push(`**Overall Risk Level: ${riskLevel}** — ${topRisks.length} risks require active management.`, '');
|
|
316
|
+
for (const r of topRisks) {
|
|
317
|
+
lines.push(`- **${r.category}** (${r.likelihood} likelihood, ${r.impact} impact): ${r.risk}`);
|
|
273
318
|
}
|
|
319
|
+
lines.push('');
|
|
320
|
+
// Recommended Next Steps — time-bound
|
|
321
|
+
lines.push('## Recommended Next Steps', '');
|
|
322
|
+
const steps = buildDomainNextSteps(recommendation, extracted);
|
|
323
|
+
for (const step of steps) {
|
|
324
|
+
lines.push(step);
|
|
325
|
+
}
|
|
326
|
+
lines.push('');
|
|
327
|
+
// Provenance
|
|
328
|
+
const sources = platformResults.filter(r => r.status >= 200 && r.status < 300).map(r => `${r.domain}/${r.agent}`);
|
|
329
|
+
lines.push('---', '');
|
|
330
|
+
lines.push(`*Sources: ${sources.slice(0, 8).join(', ')}${sources.length > 8 ? ` + ${sources.length - 8} more` : ''}*`);
|
|
274
331
|
lines.push(`*Generated: ${now}*`);
|
|
275
332
|
return lines.join('\n');
|
|
276
333
|
}
|
|
@@ -282,140 +339,109 @@ export function renderDecisionMemo(query, simulationResult, platformResults) {
|
|
|
282
339
|
const simPayload = extractSignalPayload(simulationResult);
|
|
283
340
|
const simData = simPayload.data ?? {};
|
|
284
341
|
const successProb = extractSuccessProbability(simData);
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
const riskScoreData = extractAgentData(platformResults, 'platform', 'risk-score');
|
|
342
|
+
const extracted = extractScenarioFromQuery(query);
|
|
343
|
+
const problemStatement = distillProblemStatement(query);
|
|
344
|
+
const fin = extractFinancials(simData, platformResults);
|
|
345
|
+
const risks = generateDomainRisks(query, extracted);
|
|
346
|
+
const primarySystem = extracted.systems[0] ?? 'the target platform';
|
|
291
347
|
const plannerData = extractAgentData(platformResults, 'copilot', 'planner');
|
|
292
348
|
let recommendation = 'DEFER';
|
|
293
|
-
let rationale = '
|
|
349
|
+
let rationale = 'Further analysis recommended before committing resources.';
|
|
294
350
|
if (successProb >= 0.9) {
|
|
295
351
|
recommendation = 'PROCEED';
|
|
296
|
-
rationale = 'High probability of success with manageable risks.';
|
|
352
|
+
rationale = 'High probability of success with manageable risks. Full deployment recommended.';
|
|
297
353
|
}
|
|
298
354
|
else if (successProb >= 0.7) {
|
|
299
355
|
recommendation = 'CONDITIONAL PROCEED';
|
|
300
|
-
rationale = 'Moderate confidence
|
|
356
|
+
rationale = 'Moderate confidence. A scoped pilot is recommended to validate core assumptions before committing to full deployment.';
|
|
301
357
|
}
|
|
302
|
-
//
|
|
303
|
-
const extracted = extractScenarioFromQuery(query);
|
|
304
|
-
const problemStatement = distillProblemStatement(query);
|
|
358
|
+
// ADR-PIPELINE-024: Structured decision package
|
|
305
359
|
const lines = [
|
|
306
360
|
'# Decision Memo',
|
|
307
361
|
'',
|
|
308
362
|
`**Date:** ${now}`,
|
|
309
363
|
`**Subject:** ${problemStatement}`,
|
|
364
|
+
`**Decision Requested:** Approval to proceed with ${successProb >= 0.7 ? 'scoped pilot' : 'feasibility investigation'}`,
|
|
310
365
|
'',
|
|
311
366
|
'---',
|
|
312
367
|
'',
|
|
313
368
|
'## Recommendation',
|
|
314
369
|
'',
|
|
315
|
-
|
|
370
|
+
`**${recommendation}** — ${rationale}`,
|
|
371
|
+
'',
|
|
372
|
+
`Success probability: ${(successProb * 100).toFixed(0)}%`,
|
|
316
373
|
'',
|
|
317
|
-
|
|
374
|
+
// Business Context
|
|
375
|
+
'## Business Context', '',
|
|
376
|
+
`The organization requires ${problemStatement.toLowerCase()}. ` +
|
|
377
|
+
`Current manual processes limit visibility and create operational inefficiency across ` +
|
|
378
|
+
`${extracted.stakeholders.slice(0, 3).join(', ') || 'multiple business units'}. ` +
|
|
379
|
+
`${primarySystem} serves as the system of record, and any solution must integrate non-disruptively.`,
|
|
318
380
|
'',
|
|
319
|
-
|
|
381
|
+
// Options Considered
|
|
382
|
+
'## Options Considered', '',
|
|
383
|
+
'| Option | Description | Investment | Timeline | Risk Level | Recommendation |',
|
|
384
|
+
'|--------|-------------|-----------|----------|------------|---------------|',
|
|
385
|
+
`| **A. Scoped Pilot** | Validate with subset of data and ${extracted.domain_entities.slice(0, 2).join(', ') || 'core entities'} | ${fin.budget || 'TBD'} (pilot scope) | 8-12 weeks | Low | **Recommended** |`,
|
|
386
|
+
`| **B. Full Deployment** | Enterprise-wide rollout across all ${extracted.systems.length > 0 ? extracted.systems.join(', ') : 'systems'} | ${fin.budget || 'TBD'} | ${safeString(simData, 'timeline_estimate') || '16-24 weeks'} | Medium | After pilot validation |`,
|
|
387
|
+
`| **C. Do Nothing** | Continue with manual processes | $0 | N/A | High | Not recommended — costs compound |`,
|
|
320
388
|
'',
|
|
321
389
|
];
|
|
322
|
-
//
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (hasFinancialData) {
|
|
339
|
-
lines.push('## Financial Impact', '');
|
|
340
|
-
// Simulation-sourced financial data
|
|
341
|
-
const budget = simBudget || fmBudget;
|
|
342
|
-
const roi = simRoi || fmRoi;
|
|
343
|
-
const npv = simNpv || fmNpv;
|
|
344
|
-
const payback = simPayback || fmPayback;
|
|
345
|
-
if (budget)
|
|
346
|
-
lines.push(`- **Total Investment:** ${budget}`);
|
|
347
|
-
if (roi)
|
|
348
|
-
lines.push(`- **Expected ROI:** ${roi}`);
|
|
349
|
-
if (npv)
|
|
350
|
-
lines.push(`- **5-Year NPV:** ${npv}`);
|
|
351
|
-
if (payback)
|
|
352
|
-
lines.push(`- **Payback Period:** ${payback}`);
|
|
353
|
-
if (simRevenue)
|
|
354
|
-
lines.push(`- **Projected Revenue Impact:** ${simRevenue}`);
|
|
355
|
-
if (simCostSavings)
|
|
356
|
-
lines.push(`- **Cost Savings:** ${simCostSavings}`);
|
|
357
|
-
// Enrich with costops agent data if available
|
|
358
|
-
if (roiData) {
|
|
359
|
-
const agentRoi = safeString(roiData, 'roi') || safeString(roiData, 'expected_roi');
|
|
360
|
-
const agentPayback = safeString(roiData, 'payback_period') || safeString(roiData, 'payback');
|
|
361
|
-
const agentCost = safeString(roiData, 'total_cost') || safeString(roiData, 'estimated_cost');
|
|
362
|
-
if (agentRoi && !roi)
|
|
363
|
-
lines.push(`- **Expected ROI:** ${agentRoi}`);
|
|
364
|
-
if (agentPayback && !payback)
|
|
365
|
-
lines.push(`- **Payback Period:** ${agentPayback}`);
|
|
366
|
-
if (agentCost && !budget)
|
|
367
|
-
lines.push(`- **Estimated Cost:** ${agentCost}`);
|
|
368
|
-
const insights = synthesizeAgentInsights(roiData, 'costops-roi');
|
|
369
|
-
if (insights.length > 0 && insights.some(l => l.trim().length > 0))
|
|
370
|
-
lines.push('', ...insights);
|
|
371
|
-
}
|
|
372
|
-
if (tradeoffData) {
|
|
373
|
-
lines.push('', '**Cost-Quality Tradeoff:**');
|
|
374
|
-
const insights = synthesizeAgentInsights(tradeoffData, 'costops-tradeoff');
|
|
375
|
-
lines.push(...insights);
|
|
376
|
-
}
|
|
390
|
+
// Financial Impact
|
|
391
|
+
lines.push('## Financial Impact', '');
|
|
392
|
+
if (fin.hasData) {
|
|
393
|
+
lines.push('| Metric | Value |', '|--------|-------|');
|
|
394
|
+
if (fin.budget)
|
|
395
|
+
lines.push(`| Total Investment | ${fin.budget} |`);
|
|
396
|
+
if (fin.roi)
|
|
397
|
+
lines.push(`| Expected ROI | ${fin.roi} |`);
|
|
398
|
+
if (fin.npv)
|
|
399
|
+
lines.push(`| 5-Year NPV | ${fin.npv} |`);
|
|
400
|
+
if (fin.payback)
|
|
401
|
+
lines.push(`| Payback Period | ${fin.payback} |`);
|
|
402
|
+
if (fin.revenue)
|
|
403
|
+
lines.push(`| Revenue Impact | ${fin.revenue} |`);
|
|
404
|
+
if (fin.costSavings)
|
|
405
|
+
lines.push(`| Cost Savings | ${fin.costSavings} |`);
|
|
377
406
|
lines.push('');
|
|
378
407
|
}
|
|
379
|
-
lines.push('## Risk Summary', '');
|
|
380
|
-
// Combine simulation risks with platform risk-score agent
|
|
381
|
-
const allRisks = [...riskFactors];
|
|
382
|
-
if (riskScoreData) {
|
|
383
|
-
const agentRisks = safeArray(riskScoreData, 'risk_factors')
|
|
384
|
-
.concat(safeArray(riskScoreData, 'risks'))
|
|
385
|
-
.concat(safeArray(riskScoreData, 'factors'));
|
|
386
|
-
allRisks.push(...agentRisks);
|
|
387
|
-
}
|
|
388
|
-
if (allRisks.length > 0) {
|
|
389
|
-
for (const risk of allRisks) {
|
|
390
|
-
lines.push(`- ${typeof risk === 'string' ? risk : JSON.stringify(risk)}`);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
408
|
else {
|
|
394
|
-
lines.push('
|
|
409
|
+
lines.push('Financial model to be developed during discovery phase. Key inputs: implementation cost, operational savings, and revenue impact.', '');
|
|
395
410
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
411
|
+
// Risk Assessment Summary — never empty
|
|
412
|
+
lines.push('## Risk Assessment', '');
|
|
413
|
+
lines.push('| # | Risk | Category | Likelihood | Impact | Mitigation |');
|
|
414
|
+
lines.push('|---|------|----------|-----------|--------|------------|');
|
|
415
|
+
for (let i = 0; i < Math.min(risks.length, 5); i++) {
|
|
416
|
+
const r = risks[i];
|
|
417
|
+
lines.push(`| ${i + 1} | ${r.risk} | ${r.category} | ${r.likelihood} | ${r.impact} | ${r.mitigation} |`);
|
|
400
418
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
lines.push(`- ${typeof rec === 'object' && rec !== null ? JSON.stringify(rec) : String(rec)}`);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
// ADR-PIPELINE-020: Implementation approach from copilot/planner
|
|
419
|
+
lines.push('');
|
|
420
|
+
// Implementation Approach
|
|
421
|
+
lines.push('## Implementation Approach', '');
|
|
408
422
|
if (plannerData) {
|
|
409
|
-
lines.push('', '## Implementation Approach', '');
|
|
410
423
|
const insights = synthesizeAgentInsights(plannerData, 'copilot-planner');
|
|
411
424
|
lines.push(...insights);
|
|
412
425
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
lines.push(`*Sources: ${sources.join(', ')}*`);
|
|
426
|
+
else {
|
|
427
|
+
const steps = buildDomainNextSteps(recommendation, extracted);
|
|
428
|
+
for (const step of steps)
|
|
429
|
+
lines.push(step);
|
|
418
430
|
}
|
|
431
|
+
lines.push('');
|
|
432
|
+
// Stakeholder Impact
|
|
433
|
+
lines.push('## Stakeholder Impact', '');
|
|
434
|
+
lines.push('| Stakeholder | Impact | Action Required |');
|
|
435
|
+
lines.push('|-------------|--------|----------------|');
|
|
436
|
+
lines.push(`| Executive Sponsor | Budget approval, strategic alignment | Review financial model and approve pilot scope |`);
|
|
437
|
+
lines.push(`| ${extracted.stakeholders[0] || 'Technology Lead'} | Architecture sign-off | Validate ${primarySystem} integration approach |`);
|
|
438
|
+
lines.push(`| ${extracted.stakeholders[1] || 'Operations Team'} | Process change, pilot participation | Participate in pilot; provide domain expertise |`);
|
|
439
|
+
lines.push(`| ${extracted.stakeholders[2] || 'Compliance / Risk'} | Governance review | Validate audit trail and approval workflow design |`);
|
|
440
|
+
lines.push('');
|
|
441
|
+
// Provenance
|
|
442
|
+
const sources = platformResults.filter(r => r.status >= 200 && r.status < 300).map(r => `${r.domain}/${r.agent}`);
|
|
443
|
+
lines.push('---', '');
|
|
444
|
+
lines.push(`*Sources: ${sources.slice(0, 6).join(', ')}${sources.length > 6 ? ` + ${sources.length - 6} more` : ''}*`);
|
|
419
445
|
lines.push(`*Generated: ${now}*`);
|
|
420
446
|
return lines.join('\n');
|
|
421
447
|
}
|
|
@@ -447,13 +473,11 @@ const SYSTEM_PATTERNS = [
|
|
|
447
473
|
[/\bcloud\s*functions\b/i, 'Cloud Functions'],
|
|
448
474
|
[/\bpub\s*\/?\s*sub\b/i, 'Pub/Sub'],
|
|
449
475
|
[/\bodata\b/i, 'OData'],
|
|
450
|
-
[/\bshopify\s*plus\b/i, 'Shopify Plus'],
|
|
451
|
-
[/\bshopify\b/i, 'Shopify'],
|
|
452
476
|
[/\byardi\s*voyager\b/i, 'Yardi Voyager'],
|
|
453
477
|
[/\byardi\b/i, 'Yardi'],
|
|
454
|
-
[/\
|
|
455
|
-
[/\
|
|
456
|
-
[/\
|
|
478
|
+
[/\binfor\s+cloudsuite\b/i, 'Infor CloudSuite'],
|
|
479
|
+
[/\binfor\b/i, 'Infor'],
|
|
480
|
+
[/\bepicor\b/i, 'Epicor'],
|
|
457
481
|
];
|
|
458
482
|
/** Domain classifiers: scenario_type detection from query content. */
|
|
459
483
|
const DOMAIN_CLASSIFIERS = [
|
|
@@ -971,15 +995,27 @@ export function buildRoadmapArtifact(query, simulationResult, platformResults) {
|
|
|
971
995
|
},
|
|
972
996
|
phases: defaultPhases,
|
|
973
997
|
success_criteria: safeArray(simData, 'recommendations').map(r => String(r)),
|
|
974
|
-
|
|
998
|
+
// ADR-PIPELINE-024: Always include domain-appropriate risks
|
|
999
|
+
risk_factors: generateDomainRisks(query, extracted).map(r => ({
|
|
1000
|
+
description: r.risk,
|
|
1001
|
+
category: r.category,
|
|
1002
|
+
likelihood: r.likelihood,
|
|
1003
|
+
impact: r.impact,
|
|
1004
|
+
mitigation: r.mitigation,
|
|
1005
|
+
})),
|
|
975
1006
|
platform_insights: platformResults
|
|
976
1007
|
.filter(r => r.agent === 'executive-summary' && r.status >= 200 && r.status < 300)
|
|
977
1008
|
.map(r => extractSignalPayload(r.response).data)
|
|
978
1009
|
.filter(Boolean),
|
|
979
|
-
// ADR-PIPELINE-020: Enrich roadmap with planner and costops data
|
|
980
1010
|
cost_estimate: extractAgentData(platformResults, 'costops', 'forecast'),
|
|
981
1011
|
implementation_plan: extractAgentData(platformResults, 'copilot', 'planner'),
|
|
982
1012
|
resource_requirements: extractAgentData(platformResults, 'costops', 'budget'),
|
|
1013
|
+
// ADR-PIPELINE-024: Risk gates between phases
|
|
1014
|
+
phase_gates: [
|
|
1015
|
+
{ after_phase: 'phase-1', gate: 'Discovery Complete', criteria: `${primarySystem} API validated, requirements signed off, team resourced`, decision: 'Proceed to build or pivot' },
|
|
1016
|
+
{ after_phase: 'phase-2', gate: 'Prototype Validated', criteria: 'Core functionality demonstrated, integration tested, stakeholder approval', decision: 'Proceed to validation or iterate' },
|
|
1017
|
+
{ after_phase: 'phase-3', gate: 'Pilot Ready', criteria: 'All tests passing, security review complete, operations runbook approved', decision: 'Deploy to production or address gaps' },
|
|
1018
|
+
],
|
|
983
1019
|
};
|
|
984
1020
|
}
|
|
985
1021
|
// ============================================================================
|
|
@@ -990,81 +1026,80 @@ export function buildRiskAssessment(query, simulationResult, platformResults) {
|
|
|
990
1026
|
const simPayload = extractSignalPayload(simulationResult);
|
|
991
1027
|
const simData = simPayload.data ?? {};
|
|
992
1028
|
const successProb = extractSuccessProbability(simData);
|
|
993
|
-
const
|
|
994
|
-
//
|
|
995
|
-
const
|
|
996
|
-
|
|
997
|
-
|
|
1029
|
+
const extracted = extractScenarioFromQuery(query);
|
|
1030
|
+
// ADR-PIPELINE-024: Generate domain risks — never return empty
|
|
1031
|
+
const domainRisks = generateDomainRisks(query, extracted);
|
|
1032
|
+
// Enrich with agent-sourced risks
|
|
1033
|
+
const riskAgentData = extractAgentData(platformResults, 'platform', 'risk-score');
|
|
998
1034
|
const sentinelAgents = extractAgentsByDomain(platformResults, 'sentinel');
|
|
999
1035
|
const shieldAgents = extractAgentsByDomain(platformResults, 'shield');
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1036
|
+
const agentRiskDescriptions = [];
|
|
1037
|
+
if (riskAgentData) {
|
|
1038
|
+
for (const r of safeArray(riskAgentData, 'risk_factors').concat(safeArray(riskAgentData, 'risks'))) {
|
|
1039
|
+
agentRiskDescriptions.push(typeof r === 'string' ? r : safeString(r, 'description') || JSON.stringify(r));
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
for (const r of safeArray(simData, 'risk_factors')) {
|
|
1043
|
+
agentRiskDescriptions.push(typeof r === 'string' ? r : JSON.stringify(r));
|
|
1044
|
+
}
|
|
1009
1045
|
for (const agent of sentinelAgents) {
|
|
1010
1046
|
const data = extractSignalPayload(agent.response).data;
|
|
1011
1047
|
if (data) {
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1014
|
-
allRiskFactors.push(typeof finding === 'string' ? finding : finding);
|
|
1048
|
+
for (const f of safeArray(data, 'findings').concat(safeArray(data, 'anomalies'))) {
|
|
1049
|
+
agentRiskDescriptions.push(typeof f === 'string' ? f : JSON.stringify(f));
|
|
1015
1050
|
}
|
|
1016
1051
|
}
|
|
1017
1052
|
}
|
|
1018
|
-
//
|
|
1053
|
+
// Merge agent risks into domain risks (avoid duplicates)
|
|
1054
|
+
for (const desc of agentRiskDescriptions) {
|
|
1055
|
+
if (desc && !domainRisks.some(r => r.risk.toLowerCase().includes(desc.toLowerCase().slice(0, 30)))) {
|
|
1056
|
+
domainRisks.push({
|
|
1057
|
+
risk: desc, category: 'Agent-Identified', likelihood: 'Medium', impact: 'Medium', score: 4,
|
|
1058
|
+
mitigation: 'To be assessed during discovery phase',
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
const maxScore = domainRisks[0]?.score ?? 0;
|
|
1063
|
+
const overallRisk = maxScore >= 6 ? 'MEDIUM' : maxScore >= 3 ? 'LOW-MEDIUM' : 'LOW';
|
|
1064
|
+
// Security findings
|
|
1019
1065
|
const securityFindings = [];
|
|
1020
1066
|
for (const agent of shieldAgents) {
|
|
1021
1067
|
const data = extractSignalPayload(agent.response).data;
|
|
1022
|
-
if (data)
|
|
1023
|
-
|
|
1024
|
-
securityFindings.push(...findings);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
// Extract observatory health data
|
|
1028
|
-
const healthFindings = [];
|
|
1029
|
-
for (const agent of observatoryAgents) {
|
|
1030
|
-
const data = extractSignalPayload(agent.response).data;
|
|
1031
|
-
if (data) {
|
|
1032
|
-
const findings = safeArray(data, 'findings').concat(safeArray(data, 'failures')).concat(safeArray(data, 'health_issues'));
|
|
1033
|
-
healthFindings.push(...findings);
|
|
1034
|
-
}
|
|
1068
|
+
if (data)
|
|
1069
|
+
securityFindings.push(...safeArray(data, 'findings').concat(safeArray(data, 'vulnerabilities')));
|
|
1035
1070
|
}
|
|
1036
1071
|
return {
|
|
1037
|
-
metadata: {
|
|
1038
|
-
title: `Risk Assessment: ${query}`,
|
|
1039
|
-
version: '1.0.0',
|
|
1040
|
-
created: now,
|
|
1041
|
-
},
|
|
1072
|
+
metadata: { title: `Risk Assessment: ${distillProblemStatement(query)}`, version: '2.0.0', created: now },
|
|
1042
1073
|
overall_risk_level: overallRisk,
|
|
1043
1074
|
success_probability: successProb,
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1075
|
+
risk_register: domainRisks.map((r, i) => ({
|
|
1076
|
+
id: `RISK-${String(i + 1).padStart(3, '0')}`,
|
|
1077
|
+
description: r.risk,
|
|
1078
|
+
category: r.category,
|
|
1079
|
+
likelihood: r.likelihood,
|
|
1080
|
+
impact: r.impact,
|
|
1081
|
+
score: r.score,
|
|
1082
|
+
mitigation: r.mitigation,
|
|
1083
|
+
owner: r.category === 'Technical' ? 'Engineering Lead' : r.category === 'Organizational' ? 'Program Manager' : r.category === 'Regulatory' ? 'Compliance Officer' : r.category === 'Financial' ? 'Finance Lead' : 'Project Manager',
|
|
1084
|
+
status: 'open',
|
|
1085
|
+
})),
|
|
1086
|
+
risk_heat_map: {
|
|
1087
|
+
high_likelihood_high_impact: domainRisks.filter(r => r.likelihood === 'High' && r.impact === 'High').map(r => r.risk),
|
|
1088
|
+
high_likelihood_medium_impact: domainRisks.filter(r => r.likelihood === 'High' && r.impact === 'Medium').map(r => r.risk),
|
|
1089
|
+
medium_likelihood_high_impact: domainRisks.filter(r => r.likelihood === 'Medium' && r.impact === 'High').map(r => r.risk),
|
|
1090
|
+
medium_likelihood_medium_impact: domainRisks.filter(r => r.likelihood === 'Medium' && r.impact === 'Medium').map(r => r.risk),
|
|
1091
|
+
low_likelihood_high_impact: domainRisks.filter(r => r.likelihood === 'Low' && r.impact === 'High').map(r => r.risk),
|
|
1092
|
+
},
|
|
1051
1093
|
security_findings: securityFindings.length > 0 ? securityFindings : null,
|
|
1052
|
-
health_findings: healthFindings.length > 0 ? healthFindings : null,
|
|
1053
|
-
sentinel_analysis: sentinelAgents.length > 0 ? sentinelAgents.map(a => ({
|
|
1054
|
-
agent: a.agent,
|
|
1055
|
-
data: extractSignalPayload(a.response).data,
|
|
1056
|
-
})) : null,
|
|
1057
1094
|
mitigation_strategy: {
|
|
1058
|
-
immediate:
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
ongoing: ['Continuous monitoring during implementation', 'Regular stakeholder reviews'],
|
|
1095
|
+
immediate: domainRisks.filter(r => r.score >= 6).map(r => r.mitigation),
|
|
1096
|
+
short_term: domainRisks.filter(r => r.score >= 3 && r.score < 6).map(r => r.mitigation),
|
|
1097
|
+
ongoing: ['Continuous risk monitoring during implementation', 'Quarterly risk review with stakeholders', 'Automated alerting for technical risks'],
|
|
1062
1098
|
},
|
|
1063
1099
|
sources: [
|
|
1064
1100
|
riskAgentData && 'platform/risk-score',
|
|
1065
1101
|
...sentinelAgents.map(a => `sentinel/${a.agent}`),
|
|
1066
1102
|
...shieldAgents.map(a => `shield/${a.agent}`),
|
|
1067
|
-
...observatoryAgents.map(a => `observatory/${a.agent}`),
|
|
1068
1103
|
].filter(Boolean),
|
|
1069
1104
|
};
|
|
1070
1105
|
}
|
|
@@ -1074,16 +1109,17 @@ export function buildRiskAssessment(query, simulationResult, platformResults) {
|
|
|
1074
1109
|
export function renderFinancialAnalysis(query, simulationResult, platformResults) {
|
|
1075
1110
|
const now = new Date().toISOString();
|
|
1076
1111
|
const problemStatement = distillProblemStatement(query);
|
|
1077
|
-
// Extract from simulation result first (primary source)
|
|
1078
1112
|
const simPayload = extractSignalPayload(simulationResult);
|
|
1079
1113
|
const simData = simPayload.data ?? {};
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1114
|
+
const fin = extractFinancials(simData, platformResults);
|
|
1115
|
+
const successProb = extractSuccessProbability(simData);
|
|
1116
|
+
const extracted = extractScenarioFromQuery(query);
|
|
1082
1117
|
const roiData = extractAgentData(platformResults, 'costops', 'roi');
|
|
1083
1118
|
const forecastData = extractAgentData(platformResults, 'costops', 'forecast');
|
|
1084
1119
|
const attributionData = extractAgentData(platformResults, 'costops', 'attribution');
|
|
1085
1120
|
const budgetData = extractAgentData(platformResults, 'costops', 'budget');
|
|
1086
1121
|
const tradeoffData = extractAgentData(platformResults, 'costops', 'tradeoff');
|
|
1122
|
+
// ADR-PIPELINE-024: Never output "pending" — always produce a model
|
|
1087
1123
|
const lines = [
|
|
1088
1124
|
'# Financial Analysis',
|
|
1089
1125
|
'',
|
|
@@ -1092,36 +1128,30 @@ export function renderFinancialAnalysis(query, simulationResult, platformResults
|
|
|
1092
1128
|
'',
|
|
1093
1129
|
'---',
|
|
1094
1130
|
'',
|
|
1131
|
+
'## Investment Summary', '',
|
|
1132
|
+
'| Metric | Value |',
|
|
1133
|
+
'|--------|-------|',
|
|
1134
|
+
`| Total Investment | ${fin.budget || 'To be quantified during discovery'} |`,
|
|
1135
|
+
`| Expected ROI | ${fin.roi || `Based on ${(successProb * 100).toFixed(0)}% success probability`} |`,
|
|
1136
|
+
`| 5-Year NPV | ${fin.npv || 'To be modeled based on pilot results'} |`,
|
|
1137
|
+
`| Payback Period | ${fin.payback || 'Projected 12-18 months (industry benchmark)'} |`,
|
|
1138
|
+
`| Revenue / Savings Impact | ${fin.revenue || fin.costSavings || 'To be quantified'} |`,
|
|
1139
|
+
'',
|
|
1095
1140
|
];
|
|
1096
|
-
// Simulation-sourced financial summary
|
|
1097
|
-
const simBudget = safeString(simData, 'budget') || safeString(simData, 'investment') || (financialModel ? safeString(financialModel, 'budget') || safeString(financialModel, 'total_investment') : '');
|
|
1098
|
-
const simRoi = safeString(simData, 'roi') || safeString(simData, 'expected_roi') || (financialModel ? safeString(financialModel, 'roi') : '');
|
|
1099
|
-
const simNpv = safeString(simData, 'npv') || safeString(simData, 'net_present_value') || (financialModel ? safeString(financialModel, 'npv') : '');
|
|
1100
|
-
const simPaybackPeriod = safeString(simData, 'payback_period') || safeString(simData, 'payback') || (financialModel ? safeString(financialModel, 'payback_period') : '');
|
|
1101
|
-
if (simBudget || simRoi || simNpv || simPaybackPeriod) {
|
|
1102
|
-
lines.push('## Financial Summary (from Simulation)', '');
|
|
1103
|
-
lines.push('| Metric | Value |', '|--------|-------|');
|
|
1104
|
-
if (simBudget)
|
|
1105
|
-
lines.push(`| Total Investment | ${simBudget} |`);
|
|
1106
|
-
if (simRoi)
|
|
1107
|
-
lines.push(`| Expected ROI | ${simRoi} |`);
|
|
1108
|
-
if (simNpv)
|
|
1109
|
-
lines.push(`| 5-Year NPV | ${simNpv} |`);
|
|
1110
|
-
if (simPaybackPeriod)
|
|
1111
|
-
lines.push(`| Payback Period | ${simPaybackPeriod} |`);
|
|
1112
|
-
lines.push('');
|
|
1113
|
-
}
|
|
1114
1141
|
// ROI Analysis
|
|
1115
1142
|
lines.push('## Return on Investment', '');
|
|
1116
1143
|
if (roiData) {
|
|
1117
1144
|
const insights = synthesizeAgentInsights(roiData, 'costops-roi');
|
|
1118
1145
|
lines.push(...insights);
|
|
1119
1146
|
}
|
|
1120
|
-
else if (
|
|
1121
|
-
lines.push(`
|
|
1147
|
+
else if (fin.roi || fin.payback) {
|
|
1148
|
+
lines.push(`The projected ROI of ${fin.roi || 'this initiative'} is based on simulation modeling ` +
|
|
1149
|
+
`with ${(successProb * 100).toFixed(0)}% confidence. ${fin.payback ? `Expected payback period: ${fin.payback}.` : ''} ` +
|
|
1150
|
+
`These projections should be validated against actual operational data during the pilot phase.`, '');
|
|
1122
1151
|
}
|
|
1123
1152
|
else {
|
|
1124
|
-
lines.push(
|
|
1153
|
+
lines.push(`ROI to be quantified during the discovery phase based on actual ${extracted.systems[0] || 'operational'} data. ` +
|
|
1154
|
+
`Industry benchmarks for ${extracted.scenario_type.replace(/-/g, ' ')} initiatives suggest 12-24 month payback periods.`, '');
|
|
1125
1155
|
}
|
|
1126
1156
|
// Cost Forecast
|
|
1127
1157
|
lines.push('## Cost Forecast', '');
|
|
@@ -1130,7 +1160,7 @@ export function renderFinancialAnalysis(query, simulationResult, platformResults
|
|
|
1130
1160
|
lines.push(...insights);
|
|
1131
1161
|
}
|
|
1132
1162
|
else {
|
|
1133
|
-
lines.push(
|
|
1163
|
+
lines.push(`Cost projections to be developed during discovery phase based on ${extracted.systems[0] || 'platform'} implementation scope and resource requirements.`, '');
|
|
1134
1164
|
}
|
|
1135
1165
|
// Cost Attribution
|
|
1136
1166
|
lines.push('## Cost Attribution', '');
|
|
@@ -1139,7 +1169,7 @@ export function renderFinancialAnalysis(query, simulationResult, platformResults
|
|
|
1139
1169
|
lines.push(...insights);
|
|
1140
1170
|
}
|
|
1141
1171
|
else {
|
|
1142
|
-
lines.push('
|
|
1172
|
+
lines.push('Typical cost distribution for enterprise implementations: Development (35-40%), Infrastructure (20-25%), Integration (15-20%), Operations & Support (15-20%). Actual breakdown to be refined during planning.', '');
|
|
1143
1173
|
}
|
|
1144
1174
|
// Budget Allocation
|
|
1145
1175
|
lines.push('## Budget Allocation', '');
|
|
@@ -1148,7 +1178,7 @@ export function renderFinancialAnalysis(query, simulationResult, platformResults
|
|
|
1148
1178
|
lines.push(...insights);
|
|
1149
1179
|
}
|
|
1150
1180
|
else {
|
|
1151
|
-
lines.push('
|
|
1181
|
+
lines.push('Budget allocation to be determined based on pilot scope and organizational resource availability. Recommended approach: 60% development, 25% infrastructure, 15% contingency.', '');
|
|
1152
1182
|
}
|
|
1153
1183
|
// Cost-Quality Tradeoff
|
|
1154
1184
|
lines.push('## Cost-Quality Tradeoff Analysis', '');
|
|
@@ -1157,11 +1187,26 @@ export function renderFinancialAnalysis(query, simulationResult, platformResults
|
|
|
1157
1187
|
lines.push(...insights);
|
|
1158
1188
|
}
|
|
1159
1189
|
else {
|
|
1160
|
-
lines.push('
|
|
1190
|
+
lines.push('Cost-quality tradeoff analysis to be conducted during pilot phase. Key tradeoff dimensions: implementation speed vs. feature completeness, custom development vs. platform capabilities, pilot scope vs. enterprise coverage.', '');
|
|
1161
1191
|
}
|
|
1162
1192
|
const sources = [roiData && 'costops/roi', forecastData && 'costops/forecast', attributionData && 'costops/attribution', budgetData && 'costops/budget', tradeoffData && 'costops/tradeoff'].filter(Boolean);
|
|
1163
1193
|
lines.push('---', '');
|
|
1164
|
-
|
|
1194
|
+
// Scenario Analysis
|
|
1195
|
+
lines.push('## Scenario Analysis', '');
|
|
1196
|
+
lines.push('| Scenario | Assumption | Investment | ROI | Probability |');
|
|
1197
|
+
lines.push('|----------|-----------|-----------|-----|------------|');
|
|
1198
|
+
if (fin.hasData) {
|
|
1199
|
+
lines.push(`| **Base Case** | Plan executes as modeled | ${fin.budget || 'TBD'} | ${fin.roi || 'Projected'} | 50% |`);
|
|
1200
|
+
lines.push(`| Optimistic | Faster adoption, lower integration costs | ${fin.budget ? fin.budget + ' (-20%)' : 'TBD'} | ${fin.roi ? fin.roi + ' (+30%)' : 'Above base'} | 25% |`);
|
|
1201
|
+
lines.push(`| Pessimistic | Slower adoption, scope growth | ${fin.budget ? fin.budget + ' (+40%)' : 'TBD'} | ${fin.roi ? 'Reduced' : 'Below base'} | 25% |`);
|
|
1202
|
+
}
|
|
1203
|
+
else {
|
|
1204
|
+
lines.push('| Base Case | Standard implementation | To be quantified | Industry benchmark | 50% |');
|
|
1205
|
+
lines.push('| Optimistic | Accelerated timeline | -20% of base | Above benchmark | 25% |');
|
|
1206
|
+
lines.push('| Pessimistic | Extended timeline | +40% of base | Below benchmark | 25% |');
|
|
1207
|
+
}
|
|
1208
|
+
lines.push('', '*Scenario analysis assumes ±20% cost variance and ±30% timeline variance from base case.*', '');
|
|
1209
|
+
lines.push(`*Sources: ${sources.length > 0 ? sources.join(', ') : 'simulation data + industry benchmarks'}*`);
|
|
1165
1210
|
lines.push(`*Generated: ${now}*`);
|
|
1166
1211
|
return lines.join('\n');
|
|
1167
1212
|
}
|
|
@@ -1194,7 +1239,7 @@ export function renderSecurityAssessment(query, _simulationResult, platformResul
|
|
|
1194
1239
|
}
|
|
1195
1240
|
}
|
|
1196
1241
|
else {
|
|
1197
|
-
lines.push('
|
|
1242
|
+
lines.push('Security assessment to be conducted during discovery phase. Key areas: data protection (PII handling), authentication/authorization model, secret management, and compliance with applicable regulatory frameworks.', '');
|
|
1198
1243
|
}
|
|
1199
1244
|
lines.push('## Governance & Compliance', '');
|
|
1200
1245
|
if (govAgents.length > 0) {
|
|
@@ -1208,7 +1253,7 @@ export function renderSecurityAssessment(query, _simulationResult, platformResul
|
|
|
1208
1253
|
}
|
|
1209
1254
|
}
|
|
1210
1255
|
else {
|
|
1211
|
-
lines.push('
|
|
1256
|
+
lines.push('Governance framework to be defined during discovery phase. Recommended controls: role-based access, audit trail for all decisions, approval workflows for operational changes, and separation of duties between analysis and execution.', '');
|
|
1212
1257
|
}
|
|
1213
1258
|
const sources = [...shieldAgents.map(a => `shield/${a.agent}`), ...govAgents.map(a => `governance-dashboard/${a.agent}`)];
|
|
1214
1259
|
lines.push('---', '');
|
|
@@ -1247,7 +1292,7 @@ export function renderIntegrationAssessment(query, _simulationResult, platformRe
|
|
|
1247
1292
|
}
|
|
1248
1293
|
}
|
|
1249
1294
|
else {
|
|
1250
|
-
lines.push(
|
|
1295
|
+
lines.push(`Integration assessment to be completed during technical spike. Key considerations: API authentication, rate limits, data format compatibility, error handling, and retry strategy for ${extracted.systems[0] || 'the target platform'}.`, '');
|
|
1251
1296
|
}
|
|
1252
1297
|
lines.push('## Edge & Resilience Patterns', '');
|
|
1253
1298
|
if (edgeAgents.length > 0) {
|
|
@@ -1261,7 +1306,7 @@ export function renderIntegrationAssessment(query, _simulationResult, platformRe
|
|
|
1261
1306
|
}
|
|
1262
1307
|
}
|
|
1263
1308
|
else {
|
|
1264
|
-
lines.push('
|
|
1309
|
+
lines.push('Resilience patterns (circuit breakers, retry with backoff, failover) to be implemented during the build phase based on integration assessment findings.', '');
|
|
1265
1310
|
}
|
|
1266
1311
|
const sources = [...connectorAgents.map(a => `connector-hub/${a.agent}`), ...edgeAgents.map(a => `edge/${a.agent}`)];
|
|
1267
1312
|
lines.push('---', '');
|