@agentblueprint/mcp-server 0.1.0 → 0.2.1
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 +40 -3
- package/dist/__tests__/renderers.test.d.ts +1 -0
- package/dist/__tests__/renderers.test.js +319 -0
- package/dist/__tests__/renderers.test.js.map +1 -0
- package/dist/__tests__/tools.test.js +302 -6
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/download.d.ts +9 -0
- package/dist/download.js +101 -0
- package/dist/download.js.map +1 -0
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/renderers.d.ts +15 -0
- package/dist/renderers.js +989 -0
- package/dist/renderers.js.map +1 -0
- package/dist/resources/blueprint.js +7 -4
- package/dist/resources/blueprint.js.map +1 -1
- package/dist/server.js +6 -4
- package/dist/server.js.map +1 -1
- package/dist/tools/download-blueprint.d.ts +16 -0
- package/dist/tools/download-blueprint.js +52 -0
- package/dist/tools/download-blueprint.js.map +1 -0
- package/dist/tools/get-blueprint.d.ts +0 -14
- package/dist/tools/get-blueprint.js +45 -15
- package/dist/tools/get-blueprint.js.map +1 -1
- package/dist/tools/get-business-case.d.ts +0 -14
- package/dist/tools/get-business-case.js +45 -14
- package/dist/tools/get-business-case.js.map +1 -1
- package/dist/tools/get-implementation-plan.d.ts +0 -14
- package/dist/tools/get-implementation-plan.js +46 -14
- package/dist/tools/get-implementation-plan.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Agent Skills directory renderer
|
|
3
|
+
// Ported from implementation-spec-export.service.ts (main app)
|
|
4
|
+
// Converts blueprint + business case + implementation plan + use case JSON
|
|
5
|
+
// into a Map<string, string> of { relativePath → fileContent }
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// HELPERS
|
|
9
|
+
// =============================================================================
|
|
10
|
+
export function slugify(input) {
|
|
11
|
+
return input
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.trim()
|
|
14
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
15
|
+
.replace(/^-+|-+$/g, '')
|
|
16
|
+
.slice(0, 60);
|
|
17
|
+
}
|
|
18
|
+
function str(val) {
|
|
19
|
+
return typeof val === 'string' ? val : '';
|
|
20
|
+
}
|
|
21
|
+
function arr(val) {
|
|
22
|
+
return Array.isArray(val) ? val : [];
|
|
23
|
+
}
|
|
24
|
+
function rec(val) {
|
|
25
|
+
return val && typeof val === 'object' && !Array.isArray(val) ? val : {};
|
|
26
|
+
}
|
|
27
|
+
function getPlatformName(bp) {
|
|
28
|
+
const pr = rec(bp.platformRecommendation);
|
|
29
|
+
const pp = rec(pr.primaryPlatform);
|
|
30
|
+
return str(pp.name) || 'Vendor-Agnostic';
|
|
31
|
+
}
|
|
32
|
+
function getAgenticPattern(bp) {
|
|
33
|
+
return str(bp.agenticPattern) || 'Multi-Agent';
|
|
34
|
+
}
|
|
35
|
+
function getTeam(bp) {
|
|
36
|
+
return arr(bp.enhancedDigitalTeam).filter((a) => !!a && typeof a === 'object');
|
|
37
|
+
}
|
|
38
|
+
function getInvestmentTier(bc) {
|
|
39
|
+
if (!bc)
|
|
40
|
+
return 'unknown';
|
|
41
|
+
const es = rec(bc.executiveSummary);
|
|
42
|
+
const ask = rec(es.ask);
|
|
43
|
+
const amount = str(ask.investmentAmount);
|
|
44
|
+
if (!amount)
|
|
45
|
+
return 'unknown';
|
|
46
|
+
const num = parseFloat(amount.replace(/[^0-9.]/g, ''));
|
|
47
|
+
if (isNaN(num))
|
|
48
|
+
return 'unknown';
|
|
49
|
+
if (num < 100000)
|
|
50
|
+
return 'low';
|
|
51
|
+
if (num < 500000)
|
|
52
|
+
return 'medium';
|
|
53
|
+
return 'high';
|
|
54
|
+
}
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// SKILL.md — FRONTMATTER
|
|
57
|
+
// =============================================================================
|
|
58
|
+
function buildSkillFrontmatter(input) {
|
|
59
|
+
const bp = input.blueprintData;
|
|
60
|
+
const team = getTeam(bp);
|
|
61
|
+
const platform = getPlatformName(bp);
|
|
62
|
+
const pattern = getAgenticPattern(bp);
|
|
63
|
+
const slug = slugify(input.blueprintTitle) || 'implementation-spec';
|
|
64
|
+
const lines = [
|
|
65
|
+
'---',
|
|
66
|
+
`name: ${slug}`,
|
|
67
|
+
'description: >-',
|
|
68
|
+
` Implementation specification for ${input.blueprintTitle}. ${team.length} AI agents,`,
|
|
69
|
+
` ${pattern} pattern, targeting ${platform}.`,
|
|
70
|
+
'compatibility: Any coding agent (Claude Code, Codex, Cursor).',
|
|
71
|
+
'metadata:',
|
|
72
|
+
' generated-by: agent-blueprint',
|
|
73
|
+
` generated-at: "${new Date().toISOString()}"`,
|
|
74
|
+
` blueprint-id: "${input.blueprintId}"`,
|
|
75
|
+
` platform: "${platform}"`,
|
|
76
|
+
` agent-count: "${team.length}"`,
|
|
77
|
+
` pattern: "${pattern}"`,
|
|
78
|
+
` investment-tier: "${getInvestmentTier(input.businessCaseData)}"`,
|
|
79
|
+
'---',
|
|
80
|
+
];
|
|
81
|
+
return lines.join('\n');
|
|
82
|
+
}
|
|
83
|
+
// =============================================================================
|
|
84
|
+
// SKILL.md — BODY
|
|
85
|
+
// =============================================================================
|
|
86
|
+
function buildSkillBody(input) {
|
|
87
|
+
const bp = input.blueprintData;
|
|
88
|
+
const bc = input.businessCaseData;
|
|
89
|
+
const team = getTeam(bp);
|
|
90
|
+
const platform = getPlatformName(bp);
|
|
91
|
+
const pattern = getAgenticPattern(bp);
|
|
92
|
+
const execSummary = str(bp.executiveSummary);
|
|
93
|
+
const lines = [];
|
|
94
|
+
// Overview
|
|
95
|
+
lines.push('# Implementation Specification', '');
|
|
96
|
+
lines.push(`> ${execSummary || input.blueprintTitle}`, '');
|
|
97
|
+
// Business Problem
|
|
98
|
+
lines.push('## Business Problem', '');
|
|
99
|
+
if (input.useCaseData) {
|
|
100
|
+
const uc = input.useCaseData;
|
|
101
|
+
if (str(uc.businessChallenge)) {
|
|
102
|
+
lines.push(str(uc.businessChallenge), '');
|
|
103
|
+
}
|
|
104
|
+
else if (str(uc.description)) {
|
|
105
|
+
lines.push(str(uc.description), '');
|
|
106
|
+
}
|
|
107
|
+
const painPoints = arr(uc.currentPainPoints);
|
|
108
|
+
if (painPoints.length > 0) {
|
|
109
|
+
lines.push('**Current pain points:**', '');
|
|
110
|
+
for (const p of painPoints)
|
|
111
|
+
lines.push(`- ${p}`);
|
|
112
|
+
lines.push('');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
lines.push(execSummary || '_See references/business-context.md for details._', '');
|
|
117
|
+
}
|
|
118
|
+
// Solution Architecture
|
|
119
|
+
lines.push('## Solution Architecture', '');
|
|
120
|
+
lines.push(`- **Platform:** ${platform}`);
|
|
121
|
+
lines.push(`- **Pattern:** ${pattern}`);
|
|
122
|
+
lines.push(`- **Agents:** ${team.length}`, '');
|
|
123
|
+
// Agent summary table
|
|
124
|
+
lines.push('| # | Agent | Role | Type |');
|
|
125
|
+
lines.push('|---|-------|------|------|');
|
|
126
|
+
team.forEach((agent, i) => {
|
|
127
|
+
const name = str(agent.name) || `Agent ${i + 1}`;
|
|
128
|
+
const role = str(agent.role) || str(rec(agent.instructions).role) || str(agent.agentRole) || '';
|
|
129
|
+
const type = str(agent.agentRole) || str(agent.orchestrationRole) || str(agent.type) || 'Worker';
|
|
130
|
+
lines.push(`| ${i + 1} | ${name} | ${role} | ${type} |`);
|
|
131
|
+
});
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push('> Full agent specifications in `references/agent-specifications.md`', '');
|
|
134
|
+
// Phase 1: Pilot
|
|
135
|
+
lines.push('## Phase 1: Pilot', '');
|
|
136
|
+
const phases = arr(bp.phases);
|
|
137
|
+
const pilotPhase = phases.find((p) => str(p?.name).toLowerCase().includes('pilot') || str(p?.name).toLowerCase().includes('phase 1'));
|
|
138
|
+
if (pilotPhase) {
|
|
139
|
+
const p = rec(pilotPhase);
|
|
140
|
+
if (str(p.phaseGoal))
|
|
141
|
+
lines.push(`**Goal:** ${str(p.phaseGoal)}`, '');
|
|
142
|
+
if (p.durationWeeks)
|
|
143
|
+
lines.push(`**Duration:** ${p.durationWeeks} weeks`);
|
|
144
|
+
if (str(p.phaseCost))
|
|
145
|
+
lines.push(`**Cost target:** ${str(p.phaseCost)}`);
|
|
146
|
+
lines.push('');
|
|
147
|
+
const workstreams = arr(p.workstreams);
|
|
148
|
+
if (workstreams.length > 0) {
|
|
149
|
+
lines.push('**Pilot workstreams:**', '');
|
|
150
|
+
for (const ws of workstreams) {
|
|
151
|
+
const w = rec(ws);
|
|
152
|
+
lines.push(`- ${str(w.title)}`);
|
|
153
|
+
}
|
|
154
|
+
lines.push('');
|
|
155
|
+
}
|
|
156
|
+
const gate = rec(p.decisionGate);
|
|
157
|
+
if (gate.criteria) {
|
|
158
|
+
lines.push('**Decision gate criteria:**', '');
|
|
159
|
+
for (const c of arr(gate.criteria)) {
|
|
160
|
+
const cr = rec(c);
|
|
161
|
+
const label = str(cr.name) || str(cr.criterion) || str(cr.metric) || str(cr.description) || 'Unnamed criterion';
|
|
162
|
+
lines.push(`- ${label}: ${str(cr.target) || str(cr.threshold)}`);
|
|
163
|
+
}
|
|
164
|
+
lines.push('');
|
|
165
|
+
}
|
|
166
|
+
const exitCriteria = arr(p.exitCriteria);
|
|
167
|
+
if (exitCriteria.length > 0) {
|
|
168
|
+
lines.push('**Exit criteria:**', '');
|
|
169
|
+
for (const c of exitCriteria)
|
|
170
|
+
lines.push(`- ${c}`);
|
|
171
|
+
lines.push('');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
lines.push('_No pilot phase defined. See `references/implementation-roadmap.md` for phasing._', '');
|
|
176
|
+
}
|
|
177
|
+
// Phase 2: Full Implementation
|
|
178
|
+
lines.push('## Phase 2: Full Implementation', '');
|
|
179
|
+
const fullPhases = phases.filter((p) => !str(p?.name).toLowerCase().includes('pilot') && !str(p?.name).toLowerCase().includes('phase 1'));
|
|
180
|
+
if (fullPhases.length > 0) {
|
|
181
|
+
for (const phase of fullPhases) {
|
|
182
|
+
const p = rec(phase);
|
|
183
|
+
lines.push(`### ${str(p.name)}`, '');
|
|
184
|
+
if (str(p.phaseGoal))
|
|
185
|
+
lines.push(str(p.phaseGoal), '');
|
|
186
|
+
if (p.durationWeeks)
|
|
187
|
+
lines.push(`**Duration:** ${p.durationWeeks} weeks`);
|
|
188
|
+
if (str(p.phaseCost))
|
|
189
|
+
lines.push(`**Cost:** ${str(p.phaseCost)}`);
|
|
190
|
+
lines.push('');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
lines.push('_See `references/implementation-roadmap.md` for full rollout plan._', '');
|
|
195
|
+
}
|
|
196
|
+
// Financial Summary
|
|
197
|
+
lines.push('## Financial Summary', '');
|
|
198
|
+
if (bc) {
|
|
199
|
+
const benefits = rec(bc.benefits);
|
|
200
|
+
const quantifiedROI = rec(benefits.quantifiedROI);
|
|
201
|
+
if (str(quantifiedROI.roi))
|
|
202
|
+
lines.push(`- **ROI:** ${str(quantifiedROI.roi)}`);
|
|
203
|
+
if (str(quantifiedROI.npv))
|
|
204
|
+
lines.push(`- **NPV:** ${str(quantifiedROI.npv)}`);
|
|
205
|
+
if (str(quantifiedROI.paybackPeriod))
|
|
206
|
+
lines.push(`- **Payback:** ${str(quantifiedROI.paybackPeriod)}`);
|
|
207
|
+
const pilotROI = rec(quantifiedROI.pilotROI);
|
|
208
|
+
if (str(pilotROI.pilotCost) || str(pilotROI.pilotBenefit)) {
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push('**Pilot economics:**');
|
|
211
|
+
if (str(pilotROI.pilotCost))
|
|
212
|
+
lines.push(`- Pilot cost: ${str(pilotROI.pilotCost)}`);
|
|
213
|
+
if (str(pilotROI.pilotBenefit))
|
|
214
|
+
lines.push(`- Pilot benefit: ${str(pilotROI.pilotBenefit)}`);
|
|
215
|
+
if (str(pilotROI.pilotROI))
|
|
216
|
+
lines.push(`- Pilot ROI: ${str(pilotROI.pilotROI)}`);
|
|
217
|
+
}
|
|
218
|
+
lines.push('');
|
|
219
|
+
lines.push('> Full financial analysis in `references/financial-case.md`', '');
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
lines.push('_Generate a Business Case to enrich this section._', '');
|
|
223
|
+
}
|
|
224
|
+
// Agent Specifications Summary
|
|
225
|
+
lines.push('## Agent Specifications Summary', '');
|
|
226
|
+
for (const agent of team.slice(0, 5)) {
|
|
227
|
+
const name = str(agent.name);
|
|
228
|
+
const role = str(agent.role) || str(rec(agent.instructions).role) || '';
|
|
229
|
+
lines.push(`- **${name}**: ${role}`);
|
|
230
|
+
}
|
|
231
|
+
if (team.length > 5)
|
|
232
|
+
lines.push(`- _...and ${team.length - 5} more agents_`);
|
|
233
|
+
lines.push('');
|
|
234
|
+
lines.push('> Full specifications in `references/agent-specifications.md`', '');
|
|
235
|
+
// Risk & Governance Summary
|
|
236
|
+
lines.push('## Risk & Governance Summary', '');
|
|
237
|
+
const riskAssessment = rec(bp.riskAssessment);
|
|
238
|
+
const techRisks = arr(riskAssessment.technicalRisks);
|
|
239
|
+
const bizRisks = arr(riskAssessment.businessRisks);
|
|
240
|
+
if (techRisks.length > 0 || bizRisks.length > 0) {
|
|
241
|
+
if (techRisks.length > 0) {
|
|
242
|
+
lines.push('**Technical risks:**', '');
|
|
243
|
+
for (const r of techRisks.slice(0, 3))
|
|
244
|
+
lines.push(`- ${r}`);
|
|
245
|
+
lines.push('');
|
|
246
|
+
}
|
|
247
|
+
if (bizRisks.length > 0) {
|
|
248
|
+
lines.push('**Business risks:**', '');
|
|
249
|
+
for (const r of bizRisks.slice(0, 3))
|
|
250
|
+
lines.push(`- ${r}`);
|
|
251
|
+
lines.push('');
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
lines.push('_See `references/guardrails-and-governance.md` for risk details._', '');
|
|
256
|
+
}
|
|
257
|
+
lines.push('> Full governance framework in `references/guardrails-and-governance.md`', '');
|
|
258
|
+
// How to Use This Spec
|
|
259
|
+
lines.push('## How to Use This Spec', '');
|
|
260
|
+
lines.push('1. **Load this skill** into your coding agent (Claude Code, Codex, Cursor)');
|
|
261
|
+
lines.push('2. **Review** the reference files for full context');
|
|
262
|
+
lines.push('3. **Start with Phase 1** (Pilot) — implement the lead agent first');
|
|
263
|
+
lines.push('4. **Use decision gates** to validate before expanding to full implementation');
|
|
264
|
+
lines.push('5. **Reference `scripts/validate-spec.sh`** to verify spec completeness', '');
|
|
265
|
+
// Generated By
|
|
266
|
+
lines.push('---', '');
|
|
267
|
+
lines.push('Generated by [Agent Blueprint](https://app.agentblueprint.ai)', '');
|
|
268
|
+
return lines.join('\n');
|
|
269
|
+
}
|
|
270
|
+
// =============================================================================
|
|
271
|
+
// REFERENCE FILES
|
|
272
|
+
// =============================================================================
|
|
273
|
+
function buildBusinessContext(input) {
|
|
274
|
+
const bp = input.blueprintData;
|
|
275
|
+
const uc = input.useCaseData;
|
|
276
|
+
const lines = ['# Business Context', ''];
|
|
277
|
+
const execSummary = str(bp.executiveSummary);
|
|
278
|
+
if (execSummary) {
|
|
279
|
+
lines.push('## Executive Summary', '', execSummary, '');
|
|
280
|
+
}
|
|
281
|
+
if (uc) {
|
|
282
|
+
if (str(uc.title))
|
|
283
|
+
lines.push(`## Use Case: ${str(uc.title)}`, '');
|
|
284
|
+
if (str(uc.description))
|
|
285
|
+
lines.push(str(uc.description), '');
|
|
286
|
+
const fiveWs = rec(uc.description5Ws);
|
|
287
|
+
if (fiveWs.who || fiveWs.what) {
|
|
288
|
+
lines.push('## Five Ws', '');
|
|
289
|
+
if (str(fiveWs.who))
|
|
290
|
+
lines.push(`- **Who:** ${str(fiveWs.who)}`);
|
|
291
|
+
if (str(fiveWs.what))
|
|
292
|
+
lines.push(`- **What:** ${str(fiveWs.what)}`);
|
|
293
|
+
if (str(fiveWs.where))
|
|
294
|
+
lines.push(`- **Where:** ${str(fiveWs.where)}`);
|
|
295
|
+
if (str(fiveWs.when))
|
|
296
|
+
lines.push(`- **When:** ${str(fiveWs.when)}`);
|
|
297
|
+
if (str(fiveWs.why))
|
|
298
|
+
lines.push(`- **Why:** ${str(fiveWs.why)}`);
|
|
299
|
+
lines.push('');
|
|
300
|
+
}
|
|
301
|
+
if (str(uc.businessChallenge)) {
|
|
302
|
+
lines.push('## Business Challenge', '', str(uc.businessChallenge), '');
|
|
303
|
+
}
|
|
304
|
+
const painPoints = arr(uc.currentPainPoints);
|
|
305
|
+
if (painPoints.length > 0) {
|
|
306
|
+
lines.push('## Current Pain Points', '');
|
|
307
|
+
for (const p of painPoints)
|
|
308
|
+
lines.push(`- ${p}`);
|
|
309
|
+
lines.push('');
|
|
310
|
+
}
|
|
311
|
+
const outcomes = arr(uc.desiredBusinessOutcomes);
|
|
312
|
+
if (outcomes.length > 0) {
|
|
313
|
+
lines.push('## Desired Business Outcomes', '');
|
|
314
|
+
for (const o of outcomes)
|
|
315
|
+
lines.push(`- ${o}`);
|
|
316
|
+
lines.push('');
|
|
317
|
+
}
|
|
318
|
+
const procDoc = rec(uc.processDocumentation);
|
|
319
|
+
const steps = arr(procDoc.steps);
|
|
320
|
+
if (steps.length > 0) {
|
|
321
|
+
lines.push('## Current Process', '');
|
|
322
|
+
for (const step of steps) {
|
|
323
|
+
const s = rec(step);
|
|
324
|
+
lines.push(`${s.stepNumber || '-'}. ${str(s.description)} _(${str(s.performer) || 'Unknown'})_`);
|
|
325
|
+
}
|
|
326
|
+
lines.push('');
|
|
327
|
+
}
|
|
328
|
+
const ts = rec(uc.transformationStory);
|
|
329
|
+
if (str(ts.situation)) {
|
|
330
|
+
lines.push('## Transformation Story', '');
|
|
331
|
+
lines.push(`**Situation:** ${str(ts.situation)}`);
|
|
332
|
+
if (str(ts.complication))
|
|
333
|
+
lines.push(`**Complication:** ${str(ts.complication)}`);
|
|
334
|
+
if (str(ts.resolution))
|
|
335
|
+
lines.push(`**Resolution:** ${str(ts.resolution)}`);
|
|
336
|
+
lines.push('');
|
|
337
|
+
}
|
|
338
|
+
if (str(uc.strategicAlignment)) {
|
|
339
|
+
lines.push('## Strategic Alignment', '', str(uc.strategicAlignment), '');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
lines.push('_Use case data not available. Generate a Use Case analysis to enrich this section._', '');
|
|
344
|
+
}
|
|
345
|
+
return lines.join('\n');
|
|
346
|
+
}
|
|
347
|
+
function buildAgentSpecifications(input) {
|
|
348
|
+
const bp = input.blueprintData;
|
|
349
|
+
const team = getTeam(bp);
|
|
350
|
+
const lines = ['# Agent Specifications', ''];
|
|
351
|
+
for (const agent of team) {
|
|
352
|
+
const name = str(agent.name);
|
|
353
|
+
lines.push(`## ${name}`, '');
|
|
354
|
+
const role = str(agent.role);
|
|
355
|
+
const type = str(agent.agentRole) || str(agent.orchestrationRole) || str(agent.type) || 'Worker';
|
|
356
|
+
const supervision = str(agent.supervisionLevel) || 'Supervised';
|
|
357
|
+
lines.push(`- **Role:** ${role}`);
|
|
358
|
+
lines.push(`- **Type:** ${type}`);
|
|
359
|
+
lines.push(`- **Supervision:** ${supervision}`);
|
|
360
|
+
lines.push('');
|
|
361
|
+
const instructions = rec(agent.instructions);
|
|
362
|
+
if (str(instructions.description)) {
|
|
363
|
+
lines.push('### Instructions', '', str(instructions.description), '');
|
|
364
|
+
}
|
|
365
|
+
if (str(instructions.role)) {
|
|
366
|
+
lines.push(`**Role:** ${str(instructions.role)}`, '');
|
|
367
|
+
}
|
|
368
|
+
const steps = arr(instructions.steps);
|
|
369
|
+
if (steps.length > 0) {
|
|
370
|
+
lines.push('**Steps:**', '');
|
|
371
|
+
for (const step of steps)
|
|
372
|
+
lines.push(`1. ${step}`);
|
|
373
|
+
lines.push('');
|
|
374
|
+
}
|
|
375
|
+
const responsibilities = arr(agent.responsibilities);
|
|
376
|
+
if (responsibilities.length > 0) {
|
|
377
|
+
lines.push('### Responsibilities', '');
|
|
378
|
+
for (const r of responsibilities)
|
|
379
|
+
lines.push(`- ${r}`);
|
|
380
|
+
lines.push('');
|
|
381
|
+
}
|
|
382
|
+
const tools = arr(agent.enhancedTools);
|
|
383
|
+
if (tools.length > 0) {
|
|
384
|
+
lines.push('### Tools', '');
|
|
385
|
+
lines.push('| Tool | Category | Description |');
|
|
386
|
+
lines.push('|------|----------|-------------|');
|
|
387
|
+
for (const tool of tools) {
|
|
388
|
+
const t = rec(tool);
|
|
389
|
+
const tName = str(t.name);
|
|
390
|
+
const tCat = str(t.toolCategory) || str(t.type) || '';
|
|
391
|
+
const tDesc = str(t.description).replace(/\|/g, '\\|').slice(0, 100);
|
|
392
|
+
lines.push(`| ${tName} | ${tCat} | ${tDesc} |`);
|
|
393
|
+
}
|
|
394
|
+
lines.push('');
|
|
395
|
+
}
|
|
396
|
+
const guardrails = arr(agent.guardrails);
|
|
397
|
+
if (guardrails.length > 0) {
|
|
398
|
+
lines.push('### Guardrails', '');
|
|
399
|
+
for (const g of guardrails) {
|
|
400
|
+
const gr = rec(g);
|
|
401
|
+
lines.push(`- **${str(gr.type)}**: ${str(gr.condition) || str(gr.description)}`);
|
|
402
|
+
}
|
|
403
|
+
lines.push('');
|
|
404
|
+
}
|
|
405
|
+
const escalation = arr(agent.escalationRules);
|
|
406
|
+
if (escalation.length > 0) {
|
|
407
|
+
lines.push('### Escalation Rules', '');
|
|
408
|
+
for (const rule of escalation)
|
|
409
|
+
lines.push(`- ${rule}`);
|
|
410
|
+
lines.push('');
|
|
411
|
+
}
|
|
412
|
+
const risk = rec(agent.riskAssessment);
|
|
413
|
+
if (str(risk.level)) {
|
|
414
|
+
lines.push('### Risk Assessment', '');
|
|
415
|
+
lines.push(`- **Level:** ${str(risk.level)}`);
|
|
416
|
+
lines.push(`- **Impact:** ${str(risk.impact)}`);
|
|
417
|
+
const controls = arr(risk.controls);
|
|
418
|
+
if (controls.length > 0) {
|
|
419
|
+
lines.push('- **Controls:**');
|
|
420
|
+
for (const c of controls)
|
|
421
|
+
lines.push(` - ${c}`);
|
|
422
|
+
}
|
|
423
|
+
lines.push('');
|
|
424
|
+
}
|
|
425
|
+
const cost = rec(agent.operatingCost);
|
|
426
|
+
if (arr(cost.drivers).length > 0 || str(cost.breakeven)) {
|
|
427
|
+
lines.push('### Cost Drivers', '');
|
|
428
|
+
for (const d of arr(cost.drivers))
|
|
429
|
+
lines.push(`- ${d}`);
|
|
430
|
+
if (str(cost.breakeven))
|
|
431
|
+
lines.push(`- **Breakeven:** ${str(cost.breakeven)}`);
|
|
432
|
+
lines.push('');
|
|
433
|
+
}
|
|
434
|
+
const metrics = arr(agent.successMetrics);
|
|
435
|
+
if (metrics.length > 0) {
|
|
436
|
+
lines.push('### Success Metrics', '');
|
|
437
|
+
lines.push('| Metric | Target |');
|
|
438
|
+
lines.push('|--------|--------|');
|
|
439
|
+
for (const m of metrics) {
|
|
440
|
+
const mr = rec(m);
|
|
441
|
+
lines.push(`| ${str(mr.metric)} | ${str(mr.target)} |`);
|
|
442
|
+
}
|
|
443
|
+
lines.push('');
|
|
444
|
+
}
|
|
445
|
+
lines.push('---', '');
|
|
446
|
+
}
|
|
447
|
+
return lines.join('\n');
|
|
448
|
+
}
|
|
449
|
+
function buildFinancialCase(input) {
|
|
450
|
+
const bc = input.businessCaseData;
|
|
451
|
+
const lines = ['# Financial Case', ''];
|
|
452
|
+
if (!bc) {
|
|
453
|
+
lines.push('_No business case data available. Generate a Business Case to enrich this section._', '');
|
|
454
|
+
return lines.join('\n');
|
|
455
|
+
}
|
|
456
|
+
const es = rec(bc.executiveSummary);
|
|
457
|
+
const ask = rec(es.ask);
|
|
458
|
+
if (str(es.purpose))
|
|
459
|
+
lines.push('## Purpose', '', str(es.purpose), '');
|
|
460
|
+
if (str(ask.investmentAmount) || str(ask.timeline)) {
|
|
461
|
+
lines.push('## Investment Ask', '');
|
|
462
|
+
if (str(ask.investmentAmount))
|
|
463
|
+
lines.push(`- **Amount:** ${str(ask.investmentAmount)}`);
|
|
464
|
+
if (str(ask.timeline))
|
|
465
|
+
lines.push(`- **Timeline:** ${str(ask.timeline)}`);
|
|
466
|
+
const keyOutcomes = arr(ask.keyOutcomes);
|
|
467
|
+
if (keyOutcomes.length > 0) {
|
|
468
|
+
lines.push('- **Key outcomes:**');
|
|
469
|
+
for (const o of keyOutcomes)
|
|
470
|
+
lines.push(` - ${o}`);
|
|
471
|
+
}
|
|
472
|
+
lines.push('');
|
|
473
|
+
}
|
|
474
|
+
if (str(es.valueProposition)) {
|
|
475
|
+
lines.push('## Value Proposition', '', str(es.valueProposition), '');
|
|
476
|
+
}
|
|
477
|
+
const benefits = rec(bc.benefits);
|
|
478
|
+
const qROI = rec(benefits.quantifiedROI);
|
|
479
|
+
if (str(qROI.roi) || str(qROI.npv) || str(qROI.paybackPeriod)) {
|
|
480
|
+
lines.push('## Return on Investment', '');
|
|
481
|
+
if (str(qROI.roi))
|
|
482
|
+
lines.push(`- **ROI:** ${str(qROI.roi)}`);
|
|
483
|
+
if (str(qROI.npv))
|
|
484
|
+
lines.push(`- **NPV:** ${str(qROI.npv)}`);
|
|
485
|
+
if (str(qROI.paybackPeriod))
|
|
486
|
+
lines.push(`- **Payback period:** ${str(qROI.paybackPeriod)}`);
|
|
487
|
+
lines.push('');
|
|
488
|
+
}
|
|
489
|
+
const laborDetail = rec(qROI.laborCostDetail);
|
|
490
|
+
if (str(laborDetail.annualLaborCost) || str(laborDetail.avgFullyLoadedRate)) {
|
|
491
|
+
lines.push('## Labor Cost Analysis', '');
|
|
492
|
+
if (str(laborDetail.avgFullyLoadedRate))
|
|
493
|
+
lines.push(`- **Avg. fully-loaded rate:** ${str(laborDetail.avgFullyLoadedRate)}`);
|
|
494
|
+
if (str(laborDetail.annualLaborCost))
|
|
495
|
+
lines.push(`- **Annual labor cost:** ${str(laborDetail.annualLaborCost)}`);
|
|
496
|
+
if (str(laborDetail.annualHoursAffected))
|
|
497
|
+
lines.push(`- **Annual hours affected:** ${str(laborDetail.annualHoursAffected)}`);
|
|
498
|
+
if (str(laborDetail.automationSavings))
|
|
499
|
+
lines.push(`- **Automation savings:** ${str(laborDetail.automationSavings)}`);
|
|
500
|
+
lines.push('');
|
|
501
|
+
}
|
|
502
|
+
const costBreakdown = rec(qROI.costBreakdown);
|
|
503
|
+
if (str(costBreakdown.implementation) || str(costBreakdown.annualLicensing)) {
|
|
504
|
+
lines.push('## Cost Breakdown', '');
|
|
505
|
+
if (str(costBreakdown.implementation))
|
|
506
|
+
lines.push(`- **Implementation:** ${str(costBreakdown.implementation)}`);
|
|
507
|
+
if (str(costBreakdown.annualLicensing))
|
|
508
|
+
lines.push(`- **Annual licensing:** ${str(costBreakdown.annualLicensing)}`);
|
|
509
|
+
if (str(costBreakdown.annualSupportMaintenance))
|
|
510
|
+
lines.push(`- **Annual support/maintenance:** ${str(costBreakdown.annualSupportMaintenance)}`);
|
|
511
|
+
lines.push('');
|
|
512
|
+
}
|
|
513
|
+
const pilotROI = rec(qROI.pilotROI);
|
|
514
|
+
if (str(pilotROI.pilotCost) || str(pilotROI.pilotBenefit)) {
|
|
515
|
+
lines.push('## Pilot Economics', '');
|
|
516
|
+
if (str(pilotROI.pilotCost))
|
|
517
|
+
lines.push(`- **Pilot cost:** ${str(pilotROI.pilotCost)}`);
|
|
518
|
+
if (str(pilotROI.pilotBenefit))
|
|
519
|
+
lines.push(`- **Pilot benefit:** ${str(pilotROI.pilotBenefit)}`);
|
|
520
|
+
if (str(pilotROI.pilotROI))
|
|
521
|
+
lines.push(`- **Pilot ROI:** ${str(pilotROI.pilotROI)}`);
|
|
522
|
+
if (str(pilotROI.pilotDuration))
|
|
523
|
+
lines.push(`- **Duration:** ${str(pilotROI.pilotDuration)}`);
|
|
524
|
+
lines.push('');
|
|
525
|
+
}
|
|
526
|
+
const sensitivity = rec(qROI.sensitivity);
|
|
527
|
+
if (sensitivity.conservative || sensitivity.realistic || sensitivity.optimistic) {
|
|
528
|
+
lines.push('## Sensitivity Analysis', '');
|
|
529
|
+
lines.push('| Scenario | NPV | ROI | Payback |');
|
|
530
|
+
lines.push('|----------|-----|-----|---------|');
|
|
531
|
+
for (const [label, key] of [['Conservative', 'conservative'], ['Realistic', 'realistic'], ['Optimistic', 'optimistic']]) {
|
|
532
|
+
const s = rec(sensitivity[key]);
|
|
533
|
+
lines.push(`| ${label} | ${str(s.npv)} | ${str(s.roi)} | ${str(s.paybackPeriod)} |`);
|
|
534
|
+
}
|
|
535
|
+
lines.push('');
|
|
536
|
+
}
|
|
537
|
+
const fiveYear = arr(qROI.fiveYearProjection);
|
|
538
|
+
if (fiveYear.length > 0) {
|
|
539
|
+
lines.push('## Five-Year Projection', '');
|
|
540
|
+
lines.push('| Year | Investment | Value | Net Cash Flow | Cumulative |');
|
|
541
|
+
lines.push('|------|-----------|-------|---------------|------------|');
|
|
542
|
+
for (const yr of fiveYear) {
|
|
543
|
+
const y = rec(yr);
|
|
544
|
+
lines.push(`| ${str(y.year)} | ${str(y.investment)} | ${str(y.value)} | ${str(y.netCashFlow)} | ${str(y.cumulative)} |`);
|
|
545
|
+
}
|
|
546
|
+
lines.push('');
|
|
547
|
+
}
|
|
548
|
+
const tangible = rec(benefits.tangibleBenefits);
|
|
549
|
+
if (str(tangible.costSavings) || str(tangible.processEfficiency)) {
|
|
550
|
+
lines.push('## Tangible Benefits', '');
|
|
551
|
+
if (str(tangible.costSavings))
|
|
552
|
+
lines.push(`- **Cost savings:** ${str(tangible.costSavings)}`);
|
|
553
|
+
if (str(tangible.revenueUplift))
|
|
554
|
+
lines.push(`- **Revenue uplift:** ${str(tangible.revenueUplift)}`);
|
|
555
|
+
if (str(tangible.processEfficiency))
|
|
556
|
+
lines.push(`- **Process efficiency:** ${str(tangible.processEfficiency)}`);
|
|
557
|
+
if (str(tangible.timeToMarket))
|
|
558
|
+
lines.push(`- **Time to market:** ${str(tangible.timeToMarket)}`);
|
|
559
|
+
lines.push('');
|
|
560
|
+
}
|
|
561
|
+
return lines.join('\n');
|
|
562
|
+
}
|
|
563
|
+
function buildImplementationRoadmap(input) {
|
|
564
|
+
const ip = input.implementationPlanData;
|
|
565
|
+
const lines = ['# Implementation Roadmap', ''];
|
|
566
|
+
if (!ip) {
|
|
567
|
+
lines.push('_No implementation plan data available. Generate an Implementation Plan to enrich this section._', '');
|
|
568
|
+
return lines.join('\n');
|
|
569
|
+
}
|
|
570
|
+
const overview = rec(ip.projectOverview);
|
|
571
|
+
if (str(overview.projectName)) {
|
|
572
|
+
lines.push(`## ${str(overview.projectName)}`, '');
|
|
573
|
+
}
|
|
574
|
+
if (str(overview.executiveSummary)) {
|
|
575
|
+
lines.push(str(overview.executiveSummary), '');
|
|
576
|
+
}
|
|
577
|
+
if (str(overview.scope)) {
|
|
578
|
+
lines.push('### Scope', '', str(overview.scope), '');
|
|
579
|
+
}
|
|
580
|
+
const assumptions = arr(overview.assumptions);
|
|
581
|
+
if (assumptions.length > 0) {
|
|
582
|
+
lines.push('### Assumptions', '');
|
|
583
|
+
for (const a of assumptions)
|
|
584
|
+
lines.push(`- ${a}`);
|
|
585
|
+
lines.push('');
|
|
586
|
+
}
|
|
587
|
+
const epics = arr(ip.epics);
|
|
588
|
+
if (epics.length > 0) {
|
|
589
|
+
lines.push('## Epics', '');
|
|
590
|
+
for (const epic of epics) {
|
|
591
|
+
const e = rec(epic);
|
|
592
|
+
lines.push(`### ${str(e.name)}`, '');
|
|
593
|
+
if (str(e.description))
|
|
594
|
+
lines.push(str(e.description), '');
|
|
595
|
+
lines.push(`- **Phase:** ${str(e.phase)}`);
|
|
596
|
+
lines.push(`- **Priority:** ${str(e.priority)}`);
|
|
597
|
+
if (str(e.estimatedDuration))
|
|
598
|
+
lines.push(`- **Duration:** ${str(e.estimatedDuration)}`);
|
|
599
|
+
if (str(e.businessValue))
|
|
600
|
+
lines.push(`- **Business value:** ${str(e.businessValue)}`);
|
|
601
|
+
lines.push('');
|
|
602
|
+
const ac = arr(e.acceptanceCriteria);
|
|
603
|
+
if (ac.length > 0) {
|
|
604
|
+
lines.push('**Acceptance criteria:**', '');
|
|
605
|
+
for (const c of ac)
|
|
606
|
+
lines.push(`- [ ] ${c}`);
|
|
607
|
+
lines.push('');
|
|
608
|
+
}
|
|
609
|
+
const stories = arr(e.stories);
|
|
610
|
+
if (stories.length > 0) {
|
|
611
|
+
lines.push('**User stories:**', '');
|
|
612
|
+
for (const story of stories) {
|
|
613
|
+
const s = rec(story);
|
|
614
|
+
const userStory = `As ${str(s.asA)}, I want ${str(s.iWant)}, so that ${str(s.soThat)}`;
|
|
615
|
+
lines.push(`- **${str(s.title)}**: ${userStory}`);
|
|
616
|
+
if (str(s.estimatedEffort))
|
|
617
|
+
lines.push(` - Effort: ${str(s.estimatedEffort)}`);
|
|
618
|
+
}
|
|
619
|
+
lines.push('');
|
|
620
|
+
}
|
|
621
|
+
const deps = arr(e.dependencies);
|
|
622
|
+
if (deps.length > 0) {
|
|
623
|
+
lines.push('**Dependencies:**', '');
|
|
624
|
+
for (const d of deps)
|
|
625
|
+
lines.push(`- ${d}`);
|
|
626
|
+
lines.push('');
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const agentSpecs = arr(ip.agentSpecifications);
|
|
631
|
+
if (agentSpecs.length > 0) {
|
|
632
|
+
lines.push('## Agent Build Specifications', '');
|
|
633
|
+
for (const spec of agentSpecs) {
|
|
634
|
+
const s = rec(spec);
|
|
635
|
+
lines.push(`### ${str(s.name)}`, '');
|
|
636
|
+
if (str(s.role))
|
|
637
|
+
lines.push(str(s.role), '');
|
|
638
|
+
if (str(s.instructions))
|
|
639
|
+
lines.push('**Instructions:**', '', str(s.instructions), '');
|
|
640
|
+
if (str(s.linkedStoryId))
|
|
641
|
+
lines.push(`_Linked to story: ${str(s.linkedStoryId)}_`, '');
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const resources = rec(ip.resources);
|
|
645
|
+
const timeline = rec(resources.timeline);
|
|
646
|
+
if (str(timeline.totalDuration)) {
|
|
647
|
+
lines.push('## Timeline', '');
|
|
648
|
+
lines.push(`**Total duration:** ${str(timeline.totalDuration)}`, '');
|
|
649
|
+
const timelinePhases = arr(timeline.phases);
|
|
650
|
+
if (timelinePhases.length > 0) {
|
|
651
|
+
for (const phase of timelinePhases) {
|
|
652
|
+
const p = rec(phase);
|
|
653
|
+
lines.push(`### ${str(p.name)} (${str(p.duration)})`, '');
|
|
654
|
+
for (const m of arr(p.milestones))
|
|
655
|
+
lines.push(`- ${m}`);
|
|
656
|
+
lines.push('');
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
const roles = arr(resources.roles);
|
|
661
|
+
if (roles.length > 0) {
|
|
662
|
+
lines.push('## Required Roles', '');
|
|
663
|
+
lines.push('| Role | Allocation | Duration | Key Skills |');
|
|
664
|
+
lines.push('|------|-----------|----------|------------|');
|
|
665
|
+
for (const role of roles) {
|
|
666
|
+
const r = rec(role);
|
|
667
|
+
const skills = arr(r.skillsRequired).slice(0, 3).join(', ');
|
|
668
|
+
lines.push(`| ${str(r.role)} | ${str(r.allocation)} | ${str(r.duration)} | ${skills} |`);
|
|
669
|
+
}
|
|
670
|
+
lines.push('');
|
|
671
|
+
}
|
|
672
|
+
const deps = arr(ip.dependencies);
|
|
673
|
+
if (deps.length > 0) {
|
|
674
|
+
lines.push('## Dependencies', '');
|
|
675
|
+
for (const dep of deps) {
|
|
676
|
+
const d = rec(dep);
|
|
677
|
+
lines.push(`- **${str(d.type)}** (${str(d.criticality)}): ${str(d.description)}`);
|
|
678
|
+
}
|
|
679
|
+
lines.push('');
|
|
680
|
+
}
|
|
681
|
+
return lines.join('\n');
|
|
682
|
+
}
|
|
683
|
+
function buildArchitectureDecisions(input) {
|
|
684
|
+
const bp = input.blueprintData;
|
|
685
|
+
const lines = ['# Architecture Decisions', ''];
|
|
686
|
+
const pr = rec(bp.platformRecommendation);
|
|
687
|
+
const pp = rec(pr.primaryPlatform);
|
|
688
|
+
if (str(pp.name)) {
|
|
689
|
+
lines.push(`## Platform: ${str(pp.name)}`, '');
|
|
690
|
+
if (str(pp.summary))
|
|
691
|
+
lines.push(str(pp.summary), '');
|
|
692
|
+
if (str(pp.justification))
|
|
693
|
+
lines.push(`**Justification:** ${str(pp.justification)}`, '');
|
|
694
|
+
const pros = arr(pp.pros);
|
|
695
|
+
if (pros.length > 0) {
|
|
696
|
+
lines.push('**Pros:**', '');
|
|
697
|
+
for (const p of pros)
|
|
698
|
+
lines.push(`- ${p}`);
|
|
699
|
+
lines.push('');
|
|
700
|
+
}
|
|
701
|
+
const cons = arr(pp.cons);
|
|
702
|
+
if (cons.length > 0) {
|
|
703
|
+
lines.push('**Cons:**', '');
|
|
704
|
+
for (const c of cons)
|
|
705
|
+
lines.push(`- ${c}`);
|
|
706
|
+
lines.push('');
|
|
707
|
+
}
|
|
708
|
+
if (str(pp.implementationTime))
|
|
709
|
+
lines.push(`**Implementation time:** ${str(pp.implementationTime)}`);
|
|
710
|
+
if (str(pp.estimatedCost))
|
|
711
|
+
lines.push(`**Estimated cost:** ${str(pp.estimatedCost)}`);
|
|
712
|
+
if (str(pp.integrationComplexity))
|
|
713
|
+
lines.push(`**Integration complexity:** ${str(pp.integrationComplexity)}`);
|
|
714
|
+
lines.push('');
|
|
715
|
+
}
|
|
716
|
+
const rationale = rec(bp.architectureRationale);
|
|
717
|
+
const whyAgentic = arr(rationale.whyAgentic);
|
|
718
|
+
if (whyAgentic.length > 0) {
|
|
719
|
+
lines.push('## Why Agentic AI', '');
|
|
720
|
+
for (const w of whyAgentic)
|
|
721
|
+
lines.push(`- ${w}`);
|
|
722
|
+
lines.push('');
|
|
723
|
+
}
|
|
724
|
+
const hybrid = arr(rationale.hybridComponents);
|
|
725
|
+
if (hybrid.length > 0) {
|
|
726
|
+
lines.push('## Hybrid Components', '');
|
|
727
|
+
lines.push('| Component | Approach | Rationale |');
|
|
728
|
+
lines.push('|-----------|----------|-----------|');
|
|
729
|
+
for (const h of hybrid) {
|
|
730
|
+
const hr = rec(h);
|
|
731
|
+
lines.push(`| ${str(hr.component)} | ${str(hr.approach)} | ${str(hr.rationale)} |`);
|
|
732
|
+
}
|
|
733
|
+
lines.push('');
|
|
734
|
+
}
|
|
735
|
+
const wins = arr(rationale.immediateWins);
|
|
736
|
+
if (wins.length > 0) {
|
|
737
|
+
lines.push('## Immediate Wins', '');
|
|
738
|
+
for (const w of wins)
|
|
739
|
+
lines.push(`- ${w}`);
|
|
740
|
+
lines.push('');
|
|
741
|
+
}
|
|
742
|
+
const reasoning = rec(bp.reasoning);
|
|
743
|
+
const bizDecisions = rec(reasoning.businessDecisions);
|
|
744
|
+
const patternSelection = rec(bizDecisions.patternSelection);
|
|
745
|
+
if (str(patternSelection.decision)) {
|
|
746
|
+
lines.push('## Pattern Selection', '');
|
|
747
|
+
lines.push(`**Selected:** ${str(patternSelection.decision)}`);
|
|
748
|
+
if (str(patternSelection.rationale))
|
|
749
|
+
lines.push(`**Rationale:** ${str(patternSelection.rationale)}`);
|
|
750
|
+
if (str(patternSelection.reasoning))
|
|
751
|
+
lines.push(`**Business factors:** ${str(patternSelection.reasoning)}`);
|
|
752
|
+
const alts = arr(patternSelection.alternatives);
|
|
753
|
+
if (alts.length > 0)
|
|
754
|
+
lines.push(`**Alternatives considered:** ${alts.join(', ')}`);
|
|
755
|
+
lines.push('');
|
|
756
|
+
}
|
|
757
|
+
const gaps = arr(bp.integrationGaps);
|
|
758
|
+
if (gaps.length > 0) {
|
|
759
|
+
lines.push('## Integration Gaps', '');
|
|
760
|
+
lines.push('| System | Gap Type | Severity | Impact | Recommendation |');
|
|
761
|
+
lines.push('|--------|----------|----------|--------|----------------|');
|
|
762
|
+
for (const gap of gaps) {
|
|
763
|
+
const g = rec(gap);
|
|
764
|
+
lines.push(`| ${str(g.systemNeeded)} | ${str(g.gapType)} | ${str(g.severity)} | ${str(g.impact)} | ${str(g.recommendation)} |`);
|
|
765
|
+
}
|
|
766
|
+
lines.push('');
|
|
767
|
+
}
|
|
768
|
+
const altPlatforms = arr(pr.alternativePlatforms);
|
|
769
|
+
if (altPlatforms.length > 0) {
|
|
770
|
+
lines.push('## Alternative Platforms Considered', '');
|
|
771
|
+
for (const alt of altPlatforms) {
|
|
772
|
+
const a = rec(alt);
|
|
773
|
+
lines.push(`### ${str(a.name)}`, '');
|
|
774
|
+
if (str(a.justification))
|
|
775
|
+
lines.push(str(a.justification), '');
|
|
776
|
+
if (str(a.estimatedCost))
|
|
777
|
+
lines.push(`- **Cost:** ${str(a.estimatedCost)}`);
|
|
778
|
+
if (str(a.implementationTime))
|
|
779
|
+
lines.push(`- **Timeline:** ${str(a.implementationTime)}`);
|
|
780
|
+
if (str(a.integrationComplexity))
|
|
781
|
+
lines.push(`- **Complexity:** ${str(a.integrationComplexity)}`);
|
|
782
|
+
lines.push('');
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
const feasibility = rec(bp.feasibilityIndicators);
|
|
786
|
+
if (str(feasibility.overallScore) || str(feasibility.recommendation)) {
|
|
787
|
+
lines.push('## Feasibility Assessment', '');
|
|
788
|
+
if (str(feasibility.overallScore))
|
|
789
|
+
lines.push(`**Score:** ${str(feasibility.overallScore)}`);
|
|
790
|
+
if (str(feasibility.recommendation))
|
|
791
|
+
lines.push(`**Recommendation:** ${str(feasibility.recommendation)}`);
|
|
792
|
+
lines.push('');
|
|
793
|
+
}
|
|
794
|
+
return lines.join('\n');
|
|
795
|
+
}
|
|
796
|
+
function buildGuardrailsAndGovernance(input) {
|
|
797
|
+
const bp = input.blueprintData;
|
|
798
|
+
const bc = input.businessCaseData;
|
|
799
|
+
const team = getTeam(bp);
|
|
800
|
+
const lines = ['# Guardrails & Governance', ''];
|
|
801
|
+
const riskAssessment = rec(bp.riskAssessment);
|
|
802
|
+
const techRisks = arr(riskAssessment.technicalRisks);
|
|
803
|
+
const bizRisks = arr(riskAssessment.businessRisks);
|
|
804
|
+
const mitStrategies = arr(riskAssessment.mitigationStrategies);
|
|
805
|
+
const contingencies = arr(riskAssessment.contingencyPlans);
|
|
806
|
+
if (techRisks.length > 0) {
|
|
807
|
+
lines.push('## Technical Risks', '');
|
|
808
|
+
for (const r of techRisks)
|
|
809
|
+
lines.push(`- ${r}`);
|
|
810
|
+
lines.push('');
|
|
811
|
+
}
|
|
812
|
+
if (bizRisks.length > 0) {
|
|
813
|
+
lines.push('## Business Risks', '');
|
|
814
|
+
for (const r of bizRisks)
|
|
815
|
+
lines.push(`- ${r}`);
|
|
816
|
+
lines.push('');
|
|
817
|
+
}
|
|
818
|
+
if (mitStrategies.length > 0) {
|
|
819
|
+
lines.push('## Mitigation Strategies', '');
|
|
820
|
+
for (const m of mitStrategies)
|
|
821
|
+
lines.push(`- ${m}`);
|
|
822
|
+
lines.push('');
|
|
823
|
+
}
|
|
824
|
+
if (contingencies.length > 0) {
|
|
825
|
+
lines.push('## Contingency Plans', '');
|
|
826
|
+
for (const c of contingencies)
|
|
827
|
+
lines.push(`- ${c}`);
|
|
828
|
+
lines.push('');
|
|
829
|
+
}
|
|
830
|
+
const agentsWithGuardrails = team.filter(a => arr(a.guardrails).length > 0 || arr(a.escalationRules).length > 0);
|
|
831
|
+
if (agentsWithGuardrails.length > 0) {
|
|
832
|
+
lines.push('## Agent-Level Guardrails', '');
|
|
833
|
+
for (const agent of agentsWithGuardrails) {
|
|
834
|
+
lines.push(`### ${str(agent.name)}`, '');
|
|
835
|
+
const guardrails = arr(agent.guardrails);
|
|
836
|
+
if (guardrails.length > 0) {
|
|
837
|
+
lines.push('**Guardrails:**', '');
|
|
838
|
+
for (const g of guardrails) {
|
|
839
|
+
const gr = rec(g);
|
|
840
|
+
lines.push(`- **${str(gr.type)}**: ${str(gr.condition) || str(gr.description)}`);
|
|
841
|
+
}
|
|
842
|
+
lines.push('');
|
|
843
|
+
}
|
|
844
|
+
const escalation = arr(agent.escalationRules);
|
|
845
|
+
if (escalation.length > 0) {
|
|
846
|
+
lines.push('**Escalation rules:**', '');
|
|
847
|
+
for (const rule of escalation)
|
|
848
|
+
lines.push(`- ${rule}`);
|
|
849
|
+
lines.push('');
|
|
850
|
+
}
|
|
851
|
+
const risk = rec(agent.riskAssessment);
|
|
852
|
+
if (str(risk.level)) {
|
|
853
|
+
lines.push(`**Risk:** ${str(risk.level)} — ${str(risk.impact)}`);
|
|
854
|
+
lines.push('');
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (bc) {
|
|
859
|
+
const bcRisks = rec(bc.risks);
|
|
860
|
+
const implRisks = arr(bcRisks.implementationRisks);
|
|
861
|
+
const opRisks = arr(bcRisks.operationalRisks);
|
|
862
|
+
const mitigationPlan = arr(bcRisks.mitigationPlan);
|
|
863
|
+
if (implRisks.length > 0) {
|
|
864
|
+
lines.push('## Implementation Risks (Business Case)', '');
|
|
865
|
+
lines.push('| Risk | Severity | Impact |');
|
|
866
|
+
lines.push('|------|----------|--------|');
|
|
867
|
+
for (const risk of implRisks) {
|
|
868
|
+
const r = rec(risk);
|
|
869
|
+
lines.push(`| ${str(r.title)} | ${str(r.severity)} | ${str(r.impact)} |`);
|
|
870
|
+
}
|
|
871
|
+
lines.push('');
|
|
872
|
+
}
|
|
873
|
+
if (opRisks.length > 0) {
|
|
874
|
+
lines.push('## Operational Risks (Business Case)', '');
|
|
875
|
+
lines.push('| Risk | Severity | Impact |');
|
|
876
|
+
lines.push('|------|----------|--------|');
|
|
877
|
+
for (const risk of opRisks) {
|
|
878
|
+
const r = rec(risk);
|
|
879
|
+
lines.push(`| ${str(r.title)} | ${str(r.severity)} | ${str(r.impact)} |`);
|
|
880
|
+
}
|
|
881
|
+
lines.push('');
|
|
882
|
+
}
|
|
883
|
+
if (mitigationPlan.length > 0) {
|
|
884
|
+
lines.push('## Mitigation Plan', '');
|
|
885
|
+
for (const mit of mitigationPlan) {
|
|
886
|
+
const m = rec(mit);
|
|
887
|
+
lines.push(`### ${str(m.riskTitle)}`, '');
|
|
888
|
+
lines.push(`- **Strategy:** ${str(m.strategy)}`);
|
|
889
|
+
if (str(m.owner))
|
|
890
|
+
lines.push(`- **Owner:** ${str(m.owner)}`);
|
|
891
|
+
if (str(m.timeline))
|
|
892
|
+
lines.push(`- **Timeline:** ${str(m.timeline)}`);
|
|
893
|
+
lines.push('');
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return lines.join('\n');
|
|
898
|
+
}
|
|
899
|
+
function buildValidateScript() {
|
|
900
|
+
return `#!/bin/bash
|
|
901
|
+
# validate-spec.sh — Validates implementation spec structure completeness
|
|
902
|
+
# Usage: ./scripts/validate-spec.sh
|
|
903
|
+
|
|
904
|
+
set -e
|
|
905
|
+
|
|
906
|
+
ERRORS=0
|
|
907
|
+
WARNINGS=0
|
|
908
|
+
|
|
909
|
+
check_file() {
|
|
910
|
+
if [ ! -f "$1" ]; then
|
|
911
|
+
echo "ERROR: Missing required file: $1"
|
|
912
|
+
ERRORS=$((ERRORS + 1))
|
|
913
|
+
else
|
|
914
|
+
echo "OK: $1"
|
|
915
|
+
fi
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
check_optional() {
|
|
919
|
+
if [ ! -f "$1" ]; then
|
|
920
|
+
echo "WARN: Optional file missing: $1 (consider generating the missing artifact)"
|
|
921
|
+
WARNINGS=$((WARNINGS + 1))
|
|
922
|
+
else
|
|
923
|
+
echo "OK: $1"
|
|
924
|
+
fi
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
echo "=== Implementation Spec Validator ==="
|
|
928
|
+
echo ""
|
|
929
|
+
|
|
930
|
+
# Required files
|
|
931
|
+
echo "--- Required Files ---"
|
|
932
|
+
check_file "SKILL.md"
|
|
933
|
+
check_file "references/agent-specifications.md"
|
|
934
|
+
check_file "references/architecture-decisions.md"
|
|
935
|
+
|
|
936
|
+
# Check SKILL.md has frontmatter
|
|
937
|
+
if [ -f "SKILL.md" ]; then
|
|
938
|
+
if ! head -1 SKILL.md | grep -q "^---"; then
|
|
939
|
+
echo "ERROR: SKILL.md missing YAML frontmatter"
|
|
940
|
+
ERRORS=$((ERRORS + 1))
|
|
941
|
+
fi
|
|
942
|
+
fi
|
|
943
|
+
|
|
944
|
+
echo ""
|
|
945
|
+
echo "--- Optional Files ---"
|
|
946
|
+
check_optional "references/business-context.md"
|
|
947
|
+
check_optional "references/financial-case.md"
|
|
948
|
+
check_optional "references/implementation-roadmap.md"
|
|
949
|
+
check_optional "references/guardrails-and-governance.md"
|
|
950
|
+
|
|
951
|
+
echo ""
|
|
952
|
+
echo "=== Results ==="
|
|
953
|
+
echo "Errors: $ERRORS"
|
|
954
|
+
echo "Warnings: $WARNINGS"
|
|
955
|
+
|
|
956
|
+
if [ $ERRORS -gt 0 ]; then
|
|
957
|
+
echo "FAILED: Fix $ERRORS error(s) before proceeding."
|
|
958
|
+
exit 1
|
|
959
|
+
else
|
|
960
|
+
echo "PASSED"
|
|
961
|
+
exit 0
|
|
962
|
+
fi
|
|
963
|
+
`;
|
|
964
|
+
}
|
|
965
|
+
// =============================================================================
|
|
966
|
+
// MAIN RENDER FUNCTION
|
|
967
|
+
// =============================================================================
|
|
968
|
+
/**
|
|
969
|
+
* Renders a complete Agent Skills directory from blueprint data.
|
|
970
|
+
* Returns a Map of { relativePath → fileContent }.
|
|
971
|
+
*/
|
|
972
|
+
export function renderSkillDirectory(input) {
|
|
973
|
+
const files = new Map();
|
|
974
|
+
// SKILL.md
|
|
975
|
+
const frontmatter = buildSkillFrontmatter(input);
|
|
976
|
+
const body = buildSkillBody(input);
|
|
977
|
+
files.set('SKILL.md', `${frontmatter}\n\n${body}`);
|
|
978
|
+
// Reference files
|
|
979
|
+
files.set('references/business-context.md', buildBusinessContext(input));
|
|
980
|
+
files.set('references/agent-specifications.md', buildAgentSpecifications(input));
|
|
981
|
+
files.set('references/financial-case.md', buildFinancialCase(input));
|
|
982
|
+
files.set('references/implementation-roadmap.md', buildImplementationRoadmap(input));
|
|
983
|
+
files.set('references/architecture-decisions.md', buildArchitectureDecisions(input));
|
|
984
|
+
files.set('references/guardrails-and-governance.md', buildGuardrailsAndGovernance(input));
|
|
985
|
+
// Scripts
|
|
986
|
+
files.set('scripts/validate-spec.sh', buildValidateScript());
|
|
987
|
+
return files;
|
|
988
|
+
}
|
|
989
|
+
//# sourceMappingURL=renderers.js.map
|