agentblueprint 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +137 -0
  2. package/dist/__tests__/cli.test.d.ts +1 -0
  3. package/dist/__tests__/cli.test.js +136 -0
  4. package/dist/__tests__/cli.test.js.map +1 -0
  5. package/dist/__tests__/client.test.d.ts +1 -0
  6. package/dist/__tests__/client.test.js +99 -0
  7. package/dist/__tests__/client.test.js.map +1 -0
  8. package/dist/__tests__/config.test.d.ts +1 -0
  9. package/dist/__tests__/config.test.js +37 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/renderers.test.d.ts +1 -0
  12. package/dist/__tests__/renderers.test.js +471 -0
  13. package/dist/__tests__/renderers.test.js.map +1 -0
  14. package/dist/__tests__/token-store.test.d.ts +1 -0
  15. package/dist/__tests__/token-store.test.js +61 -0
  16. package/dist/__tests__/token-store.test.js.map +1 -0
  17. package/dist/__tests__/tools.test.d.ts +1 -0
  18. package/dist/__tests__/tools.test.js +379 -0
  19. package/dist/__tests__/tools.test.js.map +1 -0
  20. package/dist/cli.d.ts +2 -0
  21. package/dist/cli.js +233 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/client.d.ts +80 -0
  24. package/dist/client.js +56 -0
  25. package/dist/client.js.map +1 -0
  26. package/dist/config.d.ts +5 -0
  27. package/dist/config.js +11 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/download.d.ts +9 -0
  30. package/dist/download.js +113 -0
  31. package/dist/download.js.map +1 -0
  32. package/dist/errors.d.ts +5 -0
  33. package/dist/errors.js +18 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +4 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/renderers.d.ts +16 -0
  39. package/dist/renderers.js +1468 -0
  40. package/dist/renderers.js.map +1 -0
  41. package/dist/resources/blueprint.d.ts +14 -0
  42. package/dist/resources/blueprint.js +46 -0
  43. package/dist/resources/blueprint.js.map +1 -0
  44. package/dist/resources/blueprints.d.ts +14 -0
  45. package/dist/resources/blueprints.js +33 -0
  46. package/dist/resources/blueprints.js.map +1 -0
  47. package/dist/resources/business-profile.d.ts +14 -0
  48. package/dist/resources/business-profile.js +33 -0
  49. package/dist/resources/business-profile.js.map +1 -0
  50. package/dist/resources/spec.d.ts +14 -0
  51. package/dist/resources/spec.js +33 -0
  52. package/dist/resources/spec.js.map +1 -0
  53. package/dist/server.d.ts +3 -0
  54. package/dist/server.js +47 -0
  55. package/dist/server.js.map +1 -0
  56. package/dist/token-store.d.ts +7 -0
  57. package/dist/token-store.js +34 -0
  58. package/dist/token-store.js.map +1 -0
  59. package/dist/tools/download-blueprint.d.ts +17 -0
  60. package/dist/tools/download-blueprint.js +55 -0
  61. package/dist/tools/download-blueprint.js.map +1 -0
  62. package/dist/tools/get-blueprint.d.ts +17 -0
  63. package/dist/tools/get-blueprint.js +65 -0
  64. package/dist/tools/get-blueprint.js.map +1 -0
  65. package/dist/tools/get-business-case.d.ts +17 -0
  66. package/dist/tools/get-business-case.js +66 -0
  67. package/dist/tools/get-business-case.js.map +1 -0
  68. package/dist/tools/get-business-profile.d.ts +14 -0
  69. package/dist/tools/get-business-profile.js +21 -0
  70. package/dist/tools/get-business-profile.js.map +1 -0
  71. package/dist/tools/get-implementation-plan.d.ts +17 -0
  72. package/dist/tools/get-implementation-plan.js +67 -0
  73. package/dist/tools/get-implementation-plan.js.map +1 -0
  74. package/dist/tools/get-implementation-spec.d.ts +31 -0
  75. package/dist/tools/get-implementation-spec.js +35 -0
  76. package/dist/tools/get-implementation-spec.js.map +1 -0
  77. package/dist/tools/get-use-case.d.ts +31 -0
  78. package/dist/tools/get-use-case.js +35 -0
  79. package/dist/tools/get-use-case.js.map +1 -0
  80. package/dist/tools/list-blueprints.d.ts +22 -0
  81. package/dist/tools/list-blueprints.js +29 -0
  82. package/dist/tools/list-blueprints.js.map +1 -0
  83. package/package.json +38 -0
@@ -0,0 +1,1468 @@
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
+ const full = input
12
+ .toLowerCase()
13
+ .trim()
14
+ .replace(/[^a-z0-9]+/g, '-')
15
+ .replace(/^-+|-+$/g, '');
16
+ if (full.length <= 60)
17
+ return full;
18
+ const trimmed = full.slice(0, 60);
19
+ const lastDash = trimmed.lastIndexOf('-');
20
+ return lastDash > 20 ? trimmed.slice(0, lastDash) : trimmed;
21
+ }
22
+ function str(val) {
23
+ return typeof val === 'string' ? val : '';
24
+ }
25
+ function arr(val) {
26
+ return Array.isArray(val) ? val : [];
27
+ }
28
+ function rec(val) {
29
+ return val && typeof val === 'object' && !Array.isArray(val) ? val : {};
30
+ }
31
+ /** Returns string representation for numbers, passes through strings, '' otherwise */
32
+ function numStr(val) {
33
+ if (typeof val === 'number')
34
+ return String(val);
35
+ if (typeof val === 'string')
36
+ return val;
37
+ return '';
38
+ }
39
+ /** Checks if a string value is a placeholder/garbage value that shouldn't be rendered */
40
+ function isPlaceholder(val) {
41
+ return ['—', '–', '-', 'N/A', 'n/a', 'TBD', 'null', 'undefined', 'none'].includes(val.trim());
42
+ }
43
+ /** Strips a trailing unit suffix to prevent double-units (e.g. "3.6 months" + " months") */
44
+ function stripTrailingUnit(val, unit) {
45
+ return val.replace(new RegExp(`\\s*${unit}\\s*$`, 'i'), '');
46
+ }
47
+ /** Joins string arrays with separator; returns '' for non-arrays */
48
+ function arrStr(val, sep = ', ') {
49
+ return Array.isArray(val) ? val.filter((v) => typeof v === 'string').join(sep) : '';
50
+ }
51
+ function getPlatformName(bp) {
52
+ const pr = rec(bp.platformRecommendation);
53
+ const pp = rec(pr.primaryPlatform);
54
+ return str(pp.name) || 'Vendor-Agnostic';
55
+ }
56
+ function getAgenticPattern(bp) {
57
+ return str(bp.agenticPattern) || 'Multi-Agent';
58
+ }
59
+ function getTeam(bp) {
60
+ return arr(bp.enhancedDigitalTeam).filter((a) => !!a && typeof a === 'object');
61
+ }
62
+ function getInvestmentTier(bp, bc) {
63
+ // Primary: blueprint feasibility indicators (canonical source)
64
+ const fi = rec(bp.feasibilityIndicators);
65
+ const bpTier = str(fi.investmentTier);
66
+ if (bpTier && ['low', 'medium', 'high'].includes(bpTier))
67
+ return bpTier;
68
+ // Fallback: derive from business case ask amount (first numeric token)
69
+ if (!bc)
70
+ return 'pending';
71
+ const es = rec(bc.executiveSummary);
72
+ const ask = rec(es.ask);
73
+ const amount = str(ask.investmentAmount);
74
+ if (!amount)
75
+ return 'pending';
76
+ const match = amount.match(/[\d,]+(?:\.\d+)?/);
77
+ if (!match)
78
+ return 'pending';
79
+ const num = parseFloat(match[0].replace(/,/g, ''));
80
+ if (isNaN(num))
81
+ return 'pending';
82
+ if (num < 150000)
83
+ return 'low';
84
+ if (num < 400000)
85
+ return 'medium';
86
+ return 'high';
87
+ }
88
+ // =============================================================================
89
+ // SKILL.md — FRONTMATTER
90
+ // =============================================================================
91
+ function buildSkillFrontmatter(input) {
92
+ const bp = input.blueprintData;
93
+ const team = getTeam(bp);
94
+ const platform = getPlatformName(bp);
95
+ const pattern = getAgenticPattern(bp);
96
+ const slug = slugify(input.blueprintTitle) || 'implementation-spec';
97
+ const lines = [
98
+ '---',
99
+ `name: ${slug}`,
100
+ 'description: >-',
101
+ ` Implementation specification for ${input.blueprintTitle}. ${team.length} AI agents,`,
102
+ ` ${pattern} pattern, targeting ${platform}.`,
103
+ 'compatibility: Any coding agent (Claude Code, Codex, Cursor).',
104
+ 'metadata:',
105
+ ' generated-by: agent-blueprint',
106
+ ` generated-at: "${new Date().toISOString()}"`,
107
+ ` blueprint-id: "${input.blueprintId}"`,
108
+ ` target-platform: "${platform}"`,
109
+ ` agent-count: "${team.length}"`,
110
+ ` pattern: "${pattern}"`,
111
+ ` investment-tier: "${getInvestmentTier(input.blueprintData, input.businessCaseData)}"`,
112
+ '---',
113
+ ];
114
+ return lines.join('\n');
115
+ }
116
+ // =============================================================================
117
+ // SKILL.md — BODY
118
+ // =============================================================================
119
+ function buildSkillBody(input) {
120
+ const bp = input.blueprintData;
121
+ const bc = input.businessCaseData;
122
+ const team = getTeam(bp);
123
+ const platform = getPlatformName(bp);
124
+ const pattern = getAgenticPattern(bp);
125
+ const execSummary = str(bp.executiveSummary);
126
+ const lines = [];
127
+ // Overview
128
+ lines.push('# Implementation Specification', '');
129
+ lines.push(`> ${execSummary || input.blueprintTitle}`, '');
130
+ // Business Problem
131
+ lines.push('## Business Problem', '');
132
+ if (input.useCaseData) {
133
+ const uc = input.useCaseData;
134
+ if (str(uc.businessChallenge)) {
135
+ lines.push(str(uc.businessChallenge), '');
136
+ }
137
+ else if (str(uc.description)) {
138
+ lines.push(str(uc.description), '');
139
+ }
140
+ const painPoints = arr(uc.currentPainPoints);
141
+ if (painPoints.length > 0) {
142
+ lines.push('**Current pain points:**', '');
143
+ for (const p of painPoints)
144
+ lines.push(`- ${p}`);
145
+ lines.push('');
146
+ }
147
+ }
148
+ else {
149
+ lines.push(execSummary || '_See references/business-context.md for details._', '');
150
+ }
151
+ // Solution Architecture
152
+ lines.push('## Solution Architecture', '');
153
+ lines.push(`- **Platform:** ${platform}`);
154
+ lines.push(`- **Pattern:** ${pattern}`);
155
+ lines.push(`- **Agents:** ${team.length}`, '');
156
+ // Agent summary table
157
+ lines.push('| # | Agent | Role | Type |');
158
+ lines.push('|---|-------|------|------|');
159
+ team.forEach((agent, i) => {
160
+ const name = str(agent.name) || `Agent ${i + 1}`;
161
+ const role = str(agent.role) || str(rec(agent.instructions).role) || str(agent.agentRole) || '';
162
+ const type = str(agent.agentRole) || str(agent.orchestrationRole) || str(agent.type) || 'Worker';
163
+ lines.push(`| ${i + 1} | ${name} | ${role} | ${type} |`);
164
+ });
165
+ lines.push('');
166
+ lines.push('> Full agent specifications in `references/agent-specifications.md`', '');
167
+ // Phase rendering — prefer implementation plan epics when available
168
+ const ipEpics = input.implementationPlanData ? arr(rec(input.implementationPlanData).epics) : [];
169
+ if (ipEpics.length > 0) {
170
+ const pilotEpics = ipEpics.filter((e) => str(rec(e).phase).toLowerCase().includes('pilot'));
171
+ const fullEpics = ipEpics.filter((e) => !str(rec(e).phase).toLowerCase().includes('pilot'));
172
+ lines.push('## Phase 1: Pilot', '');
173
+ if (pilotEpics.length > 0) {
174
+ const seen = new Set();
175
+ for (const epic of pilotEpics) {
176
+ const e = rec(epic);
177
+ const name = str(e.name);
178
+ if (name && !seen.has(name)) {
179
+ seen.add(name);
180
+ lines.push(`- **${name}**${str(e.estimatedDuration) ? ` (${str(e.estimatedDuration)})` : ''}`);
181
+ }
182
+ }
183
+ lines.push('');
184
+ }
185
+ else {
186
+ lines.push('_No pilot epics defined. See `references/implementation-roadmap.md` for phasing._', '');
187
+ }
188
+ lines.push('## Phase 2: Full Implementation', '');
189
+ if (fullEpics.length > 0) {
190
+ const seen = new Set();
191
+ for (const epic of fullEpics) {
192
+ const e = rec(epic);
193
+ const name = str(e.name);
194
+ if (name && !seen.has(name)) {
195
+ seen.add(name);
196
+ lines.push(`- **${name}**${str(e.estimatedDuration) ? ` (${str(e.estimatedDuration)})` : ''}`);
197
+ }
198
+ }
199
+ lines.push('');
200
+ }
201
+ else {
202
+ lines.push('_See `references/implementation-roadmap.md` for full rollout plan._', '');
203
+ }
204
+ }
205
+ else {
206
+ lines.push('## Phase 1: Pilot', '');
207
+ const phases = arr(bp.phases);
208
+ const pilotPhase = phases.find((p) => str(p?.name).toLowerCase().includes('pilot') || str(p?.name).toLowerCase().includes('phase 1'));
209
+ if (pilotPhase) {
210
+ const p = rec(pilotPhase);
211
+ if (str(p.phaseGoal))
212
+ lines.push(`**Goal:** ${str(p.phaseGoal)}`, '');
213
+ if (p.durationWeeks)
214
+ lines.push(`**Duration:** ${p.durationWeeks} weeks`);
215
+ if (str(p.phaseCost))
216
+ lines.push(`**Cost target:** ${str(p.phaseCost)}`);
217
+ lines.push('');
218
+ const workstreams = arr(p.workstreams);
219
+ if (workstreams.length > 0) {
220
+ lines.push('**Pilot workstreams:**', '');
221
+ for (const ws of workstreams) {
222
+ const w = rec(ws);
223
+ lines.push(`- ${str(w.title)}`);
224
+ }
225
+ lines.push('');
226
+ }
227
+ const gate = rec(p.decisionGate);
228
+ if (gate.criteria) {
229
+ lines.push('**Decision gate criteria:**', '');
230
+ for (const c of arr(gate.criteria)) {
231
+ const cr = rec(c);
232
+ const label = str(cr.name) || str(cr.criterion) || str(cr.metric) || str(cr.description) || 'Unnamed criterion';
233
+ lines.push(`- ${label}: ${str(cr.target) || str(cr.threshold)}`);
234
+ }
235
+ lines.push('');
236
+ }
237
+ const exitCriteria = arr(p.exitCriteria);
238
+ if (exitCriteria.length > 0) {
239
+ lines.push('**Exit criteria:**', '');
240
+ for (const c of exitCriteria)
241
+ lines.push(`- ${c}`);
242
+ lines.push('');
243
+ }
244
+ }
245
+ else {
246
+ lines.push('_No pilot phase defined. See `references/implementation-roadmap.md` for phasing._', '');
247
+ }
248
+ lines.push('## Phase 2: Full Implementation', '');
249
+ const fullPhases = phases.filter((p) => !str(p?.name).toLowerCase().includes('pilot') && !str(p?.name).toLowerCase().includes('phase 1'));
250
+ if (fullPhases.length > 0) {
251
+ for (const phase of fullPhases) {
252
+ const p = rec(phase);
253
+ lines.push(`### ${str(p.name)}`, '');
254
+ if (str(p.phaseGoal))
255
+ lines.push(str(p.phaseGoal), '');
256
+ if (p.durationWeeks)
257
+ lines.push(`**Duration:** ${p.durationWeeks} weeks`);
258
+ if (str(p.phaseCost))
259
+ lines.push(`**Cost:** ${str(p.phaseCost)}`);
260
+ lines.push('');
261
+ }
262
+ }
263
+ else {
264
+ lines.push('_See `references/implementation-roadmap.md` for full rollout plan._', '');
265
+ }
266
+ }
267
+ // Financial Summary
268
+ lines.push('## Financial Summary', '');
269
+ if (bc) {
270
+ const benefits = rec(bc.benefits);
271
+ const quantifiedROI = rec(benefits.quantifiedROI);
272
+ if (str(quantifiedROI.roi) && !isPlaceholder(str(quantifiedROI.roi)))
273
+ lines.push(`- **ROI:** ${str(quantifiedROI.roi)}`);
274
+ if (str(quantifiedROI.npv) && !isPlaceholder(str(quantifiedROI.npv)))
275
+ lines.push(`- **NPV:** ${str(quantifiedROI.npv)}`);
276
+ if (str(quantifiedROI.paybackPeriod) && !isPlaceholder(str(quantifiedROI.paybackPeriod)))
277
+ lines.push(`- **Payback:** ${str(quantifiedROI.paybackPeriod)}`);
278
+ const pilotROI = rec(quantifiedROI.pilotROI);
279
+ const skillPilotCapex = str(rec(pilotROI.pilotCapex).value);
280
+ const skillPilotSavings = str(rec(pilotROI.pilotAnnualSavings).value);
281
+ const skillPilotYear1Net = str(rec(pilotROI.pilotYear1Net).value);
282
+ const skillPilotSuppressed = pilotROI.suppressed === true || pilotROI.suppressed === 'true';
283
+ if (!skillPilotSuppressed && (skillPilotCapex || skillPilotSavings)) {
284
+ lines.push('');
285
+ lines.push('**Pilot economics:**');
286
+ if (skillPilotCapex)
287
+ lines.push(`- Pilot capex: ${skillPilotCapex}`);
288
+ if (skillPilotSavings)
289
+ lines.push(`- Pilot annual savings: ${skillPilotSavings}`);
290
+ if (skillPilotYear1Net)
291
+ lines.push(`- Pilot Year 1 net: ${skillPilotYear1Net}`);
292
+ }
293
+ lines.push('');
294
+ lines.push('> Full financial analysis in `references/financial-case.md`', '');
295
+ }
296
+ else {
297
+ lines.push('_Generate a Business Case to enrich this section._', '');
298
+ }
299
+ // Agent Specifications Summary
300
+ lines.push('## Agent Specifications Summary', '');
301
+ for (const agent of team.slice(0, 5)) {
302
+ const name = str(agent.name);
303
+ const role = str(agent.role) || str(rec(agent.instructions).role) || '';
304
+ lines.push(`- **${name}**: ${role}`);
305
+ }
306
+ if (team.length > 5)
307
+ lines.push(`- _...and ${team.length - 5} more agents_`);
308
+ lines.push('');
309
+ lines.push('> Full specifications in `references/agent-specifications.md`', '');
310
+ // Risk & Governance Summary
311
+ lines.push('## Risk & Governance Summary', '');
312
+ const riskAssessment = rec(bp.riskAssessment);
313
+ const techRisks = arr(riskAssessment.technicalRisks);
314
+ const bizRisks = arr(riskAssessment.businessRisks);
315
+ if (techRisks.length > 0 || bizRisks.length > 0) {
316
+ if (techRisks.length > 0) {
317
+ lines.push('**Technical risks:**', '');
318
+ for (const r of techRisks.slice(0, 3))
319
+ lines.push(`- ${r}`);
320
+ lines.push('');
321
+ }
322
+ if (bizRisks.length > 0) {
323
+ lines.push('**Business risks:**', '');
324
+ for (const r of bizRisks.slice(0, 3))
325
+ lines.push(`- ${r}`);
326
+ lines.push('');
327
+ }
328
+ }
329
+ else {
330
+ lines.push('_See `references/guardrails-and-governance.md` for risk details._', '');
331
+ }
332
+ lines.push('> Full governance framework in `references/guardrails-and-governance.md`', '');
333
+ // How to Use This Spec
334
+ lines.push('## How to Use This Spec', '');
335
+ lines.push('1. **Load this skill** into your coding agent (Claude Code, Codex, Cursor)');
336
+ lines.push('2. **Review** the reference files for full context');
337
+ lines.push('3. **Start with Phase 1** (Pilot) — implement the lead agent first');
338
+ lines.push('4. **Use decision gates** to validate before expanding to full implementation');
339
+ lines.push('5. **Reference `scripts/validate-spec.sh`** to verify spec completeness', '');
340
+ // Generated By
341
+ lines.push('---', '');
342
+ lines.push('Generated by [Agent Blueprint](https://app.agentblueprint.ai)', '');
343
+ return lines.join('\n');
344
+ }
345
+ // =============================================================================
346
+ // REFERENCE FILES
347
+ // =============================================================================
348
+ function buildBusinessContext(input) {
349
+ const bp = input.blueprintData;
350
+ const uc = input.useCaseData;
351
+ const lines = ['# Business Context', ''];
352
+ const execSummary = str(bp.executiveSummary);
353
+ if (execSummary) {
354
+ lines.push('## Executive Summary', '', execSummary, '');
355
+ }
356
+ if (uc) {
357
+ if (str(uc.title))
358
+ lines.push(`## Use Case: ${str(uc.title)}`, '');
359
+ if (str(uc.description))
360
+ lines.push(str(uc.description), '');
361
+ const fiveWs = rec(uc.description5Ws);
362
+ if (fiveWs.who || fiveWs.what) {
363
+ lines.push('## Five Ws', '');
364
+ if (str(fiveWs.who))
365
+ lines.push(`- **Who:** ${str(fiveWs.who)}`);
366
+ if (str(fiveWs.what))
367
+ lines.push(`- **What:** ${str(fiveWs.what)}`);
368
+ if (str(fiveWs.where))
369
+ lines.push(`- **Where:** ${str(fiveWs.where)}`);
370
+ if (str(fiveWs.when))
371
+ lines.push(`- **When:** ${str(fiveWs.when)}`);
372
+ if (str(fiveWs.why))
373
+ lines.push(`- **Why:** ${str(fiveWs.why)}`);
374
+ lines.push('');
375
+ }
376
+ if (str(uc.businessChallenge)) {
377
+ lines.push('## Business Challenge', '', str(uc.businessChallenge), '');
378
+ }
379
+ const painPoints = arr(uc.currentPainPoints);
380
+ if (painPoints.length > 0) {
381
+ lines.push('## Current Pain Points', '');
382
+ for (const p of painPoints)
383
+ lines.push(`- ${p}`);
384
+ lines.push('');
385
+ }
386
+ const outcomes = arr(uc.desiredBusinessOutcomes);
387
+ if (outcomes.length > 0) {
388
+ lines.push('## Desired Business Outcomes', '');
389
+ for (const o of outcomes)
390
+ lines.push(`- ${o}`);
391
+ lines.push('');
392
+ }
393
+ const procDoc = rec(uc.processDocumentation);
394
+ const steps = arr(procDoc.steps);
395
+ if (steps.length > 0) {
396
+ lines.push('## Current Process', '');
397
+ for (const step of steps) {
398
+ const s = rec(step);
399
+ lines.push(`${s.stepNumber || '-'}. ${str(s.description)} _(${str(s.performer) || 'Unknown'})_`);
400
+ }
401
+ lines.push('');
402
+ }
403
+ const ts = rec(uc.transformationStory);
404
+ if (str(ts.situation)) {
405
+ lines.push('## Transformation Story', '');
406
+ lines.push(`**Situation:** ${str(ts.situation)}`);
407
+ if (str(ts.complication))
408
+ lines.push(`**Complication:** ${str(ts.complication)}`);
409
+ if (str(ts.resolution))
410
+ lines.push(`**Resolution:** ${str(ts.resolution)}`);
411
+ lines.push('');
412
+ }
413
+ if (str(uc.strategicAlignment)) {
414
+ lines.push('## Strategic Alignment', '', str(uc.strategicAlignment), '');
415
+ }
416
+ }
417
+ else {
418
+ lines.push('_Use case data not available. Generate a Use Case analysis to enrich this section._', '');
419
+ }
420
+ return lines.join('\n');
421
+ }
422
+ function buildOrganizationContext(input) {
423
+ const bp = input.businessProfileData;
424
+ const lines = ['# Organization Context', ''];
425
+ if (!bp) {
426
+ lines.push('_No business profile data available. Create a Business Profile to enrich this section._', '');
427
+ return lines.join('\n');
428
+ }
429
+ // Company overview
430
+ const companyName = str(bp.companyName);
431
+ if (companyName) {
432
+ lines.push(`## ${companyName}`, '');
433
+ }
434
+ if (str(bp.description))
435
+ lines.push(str(bp.description), '');
436
+ // Industry & scale
437
+ if (str(bp.industry) || str(bp.size) || str(bp.revenue)) {
438
+ lines.push('## Industry & Scale', '');
439
+ if (str(bp.industry))
440
+ lines.push(`- **Industry:** ${str(bp.industry)}`);
441
+ if (str(bp.size))
442
+ lines.push(`- **Company size:** ${str(bp.size)}`);
443
+ if (str(bp.revenue))
444
+ lines.push(`- **Revenue:** ${str(bp.revenue)}`);
445
+ if (str(bp.currency) && str(bp.currency) !== 'USD')
446
+ lines.push(`- **Currency:** ${str(bp.currency)}`);
447
+ lines.push('');
448
+ }
449
+ // Technology profile
450
+ const tech = rec(bp.technologyProfile);
451
+ const systems = arr(tech.systems);
452
+ const dataInfra = rec(tech.dataInfrastructure);
453
+ const integration = rec(tech.integrationCapabilities);
454
+ const security = rec(tech.securityCompliance);
455
+ if (systems.length > 0 || dataInfra.cloudPlatforms || dataInfra.dataWarehouseExists !== undefined || integration.apiReadiness || integration.apiMaturity) {
456
+ lines.push('## Technology Landscape', '');
457
+ if (systems.length > 0) {
458
+ lines.push('### Current Systems', '');
459
+ lines.push('| System | Category | Criticality |');
460
+ lines.push('|--------|----------|-------------|');
461
+ for (const sys of systems) {
462
+ const s = rec(sys);
463
+ lines.push(`| ${str(s.name)} | ${str(s.category)} | ${str(s.criticality) || str(s.businessCriticality)} |`);
464
+ }
465
+ lines.push('');
466
+ }
467
+ const cloudPlatforms = arrStr(dataInfra.cloudPlatforms);
468
+ if (cloudPlatforms || dataInfra.dataWarehouseExists !== undefined || str(dataInfra.cloudProvider)) {
469
+ lines.push('### Data Infrastructure', '');
470
+ if (cloudPlatforms)
471
+ lines.push(`- **Cloud platforms:** ${cloudPlatforms}`);
472
+ else if (str(dataInfra.cloudProvider))
473
+ lines.push(`- **Cloud provider:** ${str(dataInfra.cloudProvider)}`);
474
+ if (dataInfra.dataWarehouseExists !== undefined)
475
+ lines.push(`- **Data warehouse:** ${dataInfra.dataWarehouseExists ? 'Yes' : 'No'}`);
476
+ if (dataInfra.dataLakeExists !== undefined)
477
+ lines.push(`- **Data lake:** ${dataInfra.dataLakeExists ? 'Yes' : 'No'}`);
478
+ if (str(dataInfra.dataGovernanceMaturity))
479
+ lines.push(`- **Data governance maturity:** ${str(dataInfra.dataGovernanceMaturity)}`);
480
+ else if (str(dataInfra.dataQuality))
481
+ lines.push(`- **Data quality:** ${str(dataInfra.dataQuality)}`);
482
+ lines.push('');
483
+ }
484
+ const apiReadiness = str(integration.apiReadiness) || str(integration.apiMaturity);
485
+ const currentIntegrations = arrStr(integration.currentIntegrations);
486
+ if (apiReadiness || currentIntegrations || str(integration.integrationPatterns)) {
487
+ lines.push('### Integration Capabilities', '');
488
+ if (apiReadiness)
489
+ lines.push(`- **API readiness:** ${apiReadiness}`);
490
+ if (currentIntegrations)
491
+ lines.push(`- **Current integrations:** ${currentIntegrations}`);
492
+ else if (str(integration.integrationPatterns))
493
+ lines.push(`- **Integration patterns:** ${str(integration.integrationPatterns)}`);
494
+ if (str(integration.integrationPlatform) && !isPlaceholder(str(integration.integrationPlatform)))
495
+ lines.push(`- **Integration platform:** ${str(integration.integrationPlatform)}`);
496
+ else if (str(integration.middlewarePlatforms) && !isPlaceholder(str(integration.middlewarePlatforms)))
497
+ lines.push(`- **Middleware:** ${str(integration.middlewarePlatforms)}`);
498
+ lines.push('');
499
+ }
500
+ const complianceCerts = arrStr(security.complianceCertifications);
501
+ const privacyMeasures = arrStr(security.dataPrivacyMeasures);
502
+ if (complianceCerts || privacyMeasures || str(security.complianceFrameworks) || str(security.dataPrivacy)) {
503
+ lines.push('### Security & Compliance', '');
504
+ if (complianceCerts)
505
+ lines.push(`- **Compliance certifications:** ${complianceCerts}`);
506
+ else if (str(security.complianceFrameworks))
507
+ lines.push(`- **Compliance frameworks:** ${str(security.complianceFrameworks)}`);
508
+ if (privacyMeasures)
509
+ lines.push(`- **Data privacy measures:** ${privacyMeasures}`);
510
+ else if (str(security.dataPrivacy))
511
+ lines.push(`- **Data privacy:** ${str(security.dataPrivacy)}`);
512
+ lines.push('');
513
+ }
514
+ }
515
+ // Business operations
516
+ const ops = rec(bp.businessOperations);
517
+ const keyProcesses = arr(ops.keyProcesses);
518
+ const painPoints = arr(ops.painPoints);
519
+ const stakeholders = arr(ops.stakeholders);
520
+ if (keyProcesses.length > 0 || painPoints.length > 0) {
521
+ lines.push('## Business Operations', '');
522
+ if (keyProcesses.length > 0) {
523
+ lines.push('### Key Processes', '');
524
+ for (const proc of keyProcesses) {
525
+ const p = rec(proc);
526
+ const name = str(p.name) || str(p.processName);
527
+ const volume = str(p.volume) || str(p.transactionVolume);
528
+ if (name) {
529
+ lines.push(`- **${name}**${volume ? ` (${volume})` : ''}`);
530
+ if (str(p.frequency))
531
+ lines.push(` - Frequency: ${str(p.frequency)}`);
532
+ if (str(p.automationLevel))
533
+ lines.push(` - Automation level: ${str(p.automationLevel)}`);
534
+ }
535
+ }
536
+ lines.push('');
537
+ }
538
+ if (painPoints.length > 0) {
539
+ lines.push('### Operational Pain Points', '');
540
+ for (const pp of painPoints) {
541
+ if (typeof pp === 'string') {
542
+ lines.push(`- ${pp}`);
543
+ }
544
+ else {
545
+ const p = rec(pp);
546
+ const desc = str(p.description) || str(p.painPoint);
547
+ if (desc)
548
+ lines.push(`- ${desc}${str(p.severity) ? ` _(${str(p.severity)})_` : ''}`);
549
+ }
550
+ }
551
+ lines.push('');
552
+ }
553
+ if (stakeholders.length > 0) {
554
+ lines.push('### Key Stakeholders', '');
555
+ for (const sh of stakeholders) {
556
+ const s = rec(sh);
557
+ const role = str(s.role) || str(s.title);
558
+ const name = str(s.name);
559
+ if (role || name)
560
+ lines.push(`- **${role || name}**${name && role ? ` — ${name}` : ''}`);
561
+ }
562
+ lines.push('');
563
+ }
564
+ }
565
+ // Organizational capabilities
566
+ const caps = rec(bp.organizationalCapabilities);
567
+ const technicalTeam = rec(caps.technicalTeam);
568
+ const currentAutomation = rec(caps.currentAutomation);
569
+ const devCapacity = numStr(technicalTeam.developmentCapacity);
570
+ if (devCapacity || str(technicalTeam.size) || str(currentAutomation.level)) {
571
+ lines.push('## Organizational Capabilities', '');
572
+ if (devCapacity)
573
+ lines.push(`- **Development capacity:** ${devCapacity} FTEs`);
574
+ else if (str(technicalTeam.size))
575
+ lines.push(`- **Technical team size:** ${str(technicalTeam.size)}`);
576
+ if (str(technicalTeam.aiMlExperience))
577
+ lines.push(`- **AI/ML experience:** ${str(technicalTeam.aiMlExperience)}`);
578
+ else if (str(technicalTeam.aiExperience))
579
+ lines.push(`- **AI experience:** ${str(technicalTeam.aiExperience)}`);
580
+ if (str(currentAutomation.level))
581
+ lines.push(`- **Current automation level:** ${str(currentAutomation.level)}`);
582
+ const automatedProcesses = arrStr(currentAutomation.automatedProcesses);
583
+ if (automatedProcesses)
584
+ lines.push(`- **Automated processes:** ${automatedProcesses}`);
585
+ else if (str(currentAutomation.tools))
586
+ lines.push(`- **Automation tools:** ${str(currentAutomation.tools)}`);
587
+ lines.push('');
588
+ }
589
+ // Constraints
590
+ const constraints = rec(bp.constraintsProfile);
591
+ const budget = rec(constraints.budget);
592
+ const timeline = rec(constraints.timeline);
593
+ const technical = rec(constraints.technical);
594
+ const regulatory = rec(constraints.regulatory);
595
+ const totalBudget = str(budget.totalAiBudget) || str(budget.totalBudget);
596
+ const annualBudget = str(budget.annualOpexAvailable) || str(budget.annualBudget);
597
+ const deadlines = arrStr(timeline.criticalDeadlines);
598
+ const rolloutTimeline = str(timeline.fullRolloutTimeline) || str(timeline.preferredTimeline);
599
+ const legacyConstraints = arrStr(technical.legacySystemConstraints);
600
+ const regulations = arrStr(regulatory.industryRegulations);
601
+ if (totalBudget || deadlines || str(timeline.deadline) || regulations || str(regulatory.requirements)) {
602
+ lines.push('## Constraints', '');
603
+ if (totalBudget)
604
+ lines.push(`- **Budget:** ${totalBudget}`);
605
+ if (annualBudget)
606
+ lines.push(`- **Annual budget:** ${annualBudget}`);
607
+ if (deadlines)
608
+ lines.push(`- **Critical deadlines:** ${deadlines}`);
609
+ else if (str(timeline.deadline))
610
+ lines.push(`- **Deadline:** ${str(timeline.deadline)}`);
611
+ if (rolloutTimeline)
612
+ lines.push(`- **Rollout timeline:** ${rolloutTimeline}`);
613
+ if (legacyConstraints)
614
+ lines.push(`- **Legacy system constraints:** ${legacyConstraints}`);
615
+ else if (str(technical.limitations))
616
+ lines.push(`- **Technical limitations:** ${str(technical.limitations)}`);
617
+ if (regulations)
618
+ lines.push(`- **Industry regulations:** ${regulations}`);
619
+ else if (str(regulatory.requirements))
620
+ lines.push(`- **Regulatory:** ${str(regulatory.requirements)}`);
621
+ lines.push('');
622
+ }
623
+ // Strategic initiatives
624
+ const initiatives = arr(bp.strategicInitiatives);
625
+ if (initiatives.length > 0) {
626
+ lines.push('## Strategic Initiatives', '');
627
+ for (const init of initiatives) {
628
+ const i = rec(init);
629
+ const title = str(i.title);
630
+ if (title) {
631
+ lines.push(`### ${title}`, '');
632
+ if (str(i.description))
633
+ lines.push(str(i.description), '');
634
+ if (str(i.priority))
635
+ lines.push(`- **Priority:** ${str(i.priority)}`);
636
+ if (str(i.status))
637
+ lines.push(`- **Status:** ${str(i.status)}`);
638
+ if (str(i.budget))
639
+ lines.push(`- **Budget:** ${str(i.budget)}`);
640
+ if (str(i.timeline))
641
+ lines.push(`- **Timeline:** ${str(i.timeline)}`);
642
+ const outcomes = arr(i.expectedOutcomes);
643
+ if (outcomes.length > 0) {
644
+ lines.push('- **Expected outcomes:**');
645
+ for (const o of outcomes)
646
+ lines.push(` - ${o}`);
647
+ }
648
+ lines.push('');
649
+ }
650
+ }
651
+ }
652
+ // AI readiness
653
+ if (bp.aiReadinessScore !== null && bp.aiReadinessScore !== undefined) {
654
+ lines.push('## AI Readiness', '');
655
+ lines.push(`- **Score:** ${bp.aiReadinessScore}/100`);
656
+ lines.push('');
657
+ }
658
+ return lines.join('\n');
659
+ }
660
+ function buildAgentSpecifications(input) {
661
+ const bp = input.blueprintData;
662
+ const team = getTeam(bp);
663
+ const lines = ['# Agent Specifications', ''];
664
+ for (const agent of team) {
665
+ const name = str(agent.name);
666
+ lines.push(`## ${name}`, '');
667
+ const role = str(agent.role) || str(rec(agent.instructions).role);
668
+ const type = str(agent.agentRole) || str(agent.orchestrationRole) || str(agent.type) || 'Worker';
669
+ const supervision = str(agent.supervisionLevel) || 'Supervised';
670
+ lines.push(`- **Role:** ${role}`);
671
+ lines.push(`- **Type:** ${type}`);
672
+ lines.push(`- **Supervision:** ${supervision}`);
673
+ lines.push('');
674
+ const instructions = rec(agent.instructions);
675
+ if (str(instructions.description)) {
676
+ lines.push('### Instructions', '', str(instructions.description), '');
677
+ }
678
+ const steps = arr(instructions.steps);
679
+ if (steps.length > 0) {
680
+ lines.push('**Steps:**', '');
681
+ for (const step of steps)
682
+ lines.push(`1. ${step}`);
683
+ lines.push('');
684
+ }
685
+ const responsibilities = arr(agent.responsibilities);
686
+ if (responsibilities.length > 0) {
687
+ lines.push('### Responsibilities', '');
688
+ for (const r of responsibilities)
689
+ lines.push(`- ${r}`);
690
+ lines.push('');
691
+ }
692
+ const tools = arr(agent.enhancedTools);
693
+ if (tools.length > 0) {
694
+ lines.push('### Tools', '');
695
+ lines.push('| Tool | Category | Description |');
696
+ lines.push('|------|----------|-------------|');
697
+ for (const tool of tools) {
698
+ if (typeof tool === 'string') {
699
+ lines.push(`| ${tool} | | |`);
700
+ continue;
701
+ }
702
+ const t = rec(tool);
703
+ const tName = str(t.name);
704
+ const tCat = str(t.toolCategory) || str(t.type) || '';
705
+ const tDesc = str(t.description).replace(/\|/g, '\\|');
706
+ lines.push(`| ${tName} | ${tCat} | ${tDesc} |`);
707
+ }
708
+ lines.push('');
709
+ }
710
+ const guardrails = arr(agent.guardrails);
711
+ if (guardrails.length > 0) {
712
+ lines.push('### Guardrails', '');
713
+ for (const g of guardrails) {
714
+ const gr = rec(g);
715
+ lines.push(`- **${str(gr.type)}**: ${str(gr.condition) || str(gr.description)}`);
716
+ }
717
+ lines.push('');
718
+ }
719
+ const escalation = arr(agent.escalationRules);
720
+ if (escalation.length > 0) {
721
+ lines.push('### Escalation Rules', '');
722
+ for (const rule of escalation)
723
+ lines.push(`- ${rule}`);
724
+ lines.push('');
725
+ }
726
+ const risk = rec(agent.riskAssessment);
727
+ if (str(risk.level) && !isPlaceholder(str(risk.level))) {
728
+ lines.push('### Risk Assessment', '');
729
+ lines.push(`- **Level:** ${str(risk.level)}`);
730
+ const riskImpact = str(risk.impact);
731
+ if (riskImpact && !isPlaceholder(riskImpact))
732
+ lines.push(`- **Impact:** ${riskImpact}`);
733
+ const controls = arr(risk.controls);
734
+ if (controls.length > 0) {
735
+ lines.push('- **Controls:**');
736
+ for (const c of controls)
737
+ lines.push(` - ${c}`);
738
+ }
739
+ lines.push('');
740
+ }
741
+ const cost = rec(agent.operatingCost);
742
+ if (arr(cost.drivers).length > 0 || str(cost.breakeven)) {
743
+ lines.push('### Cost Drivers', '');
744
+ for (const d of arr(cost.drivers))
745
+ lines.push(`- ${d}`);
746
+ if (str(cost.breakeven))
747
+ lines.push(`- **Breakeven:** ${str(cost.breakeven)}`);
748
+ lines.push('');
749
+ }
750
+ const metrics = arr(agent.successMetrics);
751
+ if (metrics.length > 0) {
752
+ lines.push('### Success Metrics', '');
753
+ lines.push('| Metric | Target |');
754
+ lines.push('|--------|--------|');
755
+ for (const m of metrics) {
756
+ const mr = rec(m);
757
+ lines.push(`| ${str(mr.metric)} | ${str(mr.target)} |`);
758
+ }
759
+ lines.push('');
760
+ }
761
+ lines.push('---', '');
762
+ }
763
+ return lines.join('\n');
764
+ }
765
+ function buildFinancialCase(input) {
766
+ const bc = input.businessCaseData;
767
+ const lines = ['# Financial Case', ''];
768
+ if (!bc) {
769
+ lines.push('_No business case data available. Generate a Business Case to enrich this section._', '');
770
+ return lines.join('\n');
771
+ }
772
+ const es = rec(bc.executiveSummary);
773
+ const ask = rec(es.ask);
774
+ if (str(es.purpose))
775
+ lines.push('## Purpose', '', str(es.purpose), '');
776
+ if (str(ask.investmentAmount) || str(ask.timeline)) {
777
+ lines.push('## Investment Ask', '');
778
+ if (str(ask.investmentAmount))
779
+ lines.push(`- **Amount:** ${str(ask.investmentAmount)}`);
780
+ if (str(ask.timeline))
781
+ lines.push(`- **Timeline:** ${str(ask.timeline)}`);
782
+ const keyOutcomes = arr(ask.keyOutcomes);
783
+ if (keyOutcomes.length > 0) {
784
+ lines.push('- **Key outcomes:**');
785
+ for (const o of keyOutcomes)
786
+ lines.push(` - ${o}`);
787
+ }
788
+ lines.push('');
789
+ }
790
+ if (str(es.valueProposition)) {
791
+ lines.push('## Value Proposition', '', str(es.valueProposition), '');
792
+ }
793
+ const benefits = rec(bc.benefits);
794
+ const qROI = rec(benefits.quantifiedROI);
795
+ const roiVal = str(qROI.roi);
796
+ const npvVal = str(qROI.npv);
797
+ const paybackVal = str(qROI.paybackPeriod);
798
+ if ((roiVal && !isPlaceholder(roiVal)) || (npvVal && !isPlaceholder(npvVal)) || (paybackVal && !isPlaceholder(paybackVal))) {
799
+ lines.push('## Return on Investment', '');
800
+ if (roiVal && !isPlaceholder(roiVal))
801
+ lines.push(`- **ROI:** ${roiVal}`);
802
+ if (npvVal && !isPlaceholder(npvVal))
803
+ lines.push(`- **NPV:** ${npvVal}`);
804
+ if (paybackVal && !isPlaceholder(paybackVal))
805
+ lines.push(`- **Payback period:** ${paybackVal}`);
806
+ lines.push('');
807
+ }
808
+ // Labor cost detail (nested object: currentStateBaseline / projectedSavings)
809
+ const laborDetail = rec(qROI.laborCostDetail);
810
+ const currentBaseline = rec(laborDetail.currentStateBaseline);
811
+ const projectedSavings = rec(laborDetail.projectedSavings);
812
+ const blendedRate = str(rec(currentBaseline.blendedHourlyRate).value);
813
+ const totalAnnualCost = str(rec(currentBaseline.totalAnnualCost).value);
814
+ const totalAnnualHours = str(rec(currentBaseline.totalAnnualHours).value);
815
+ const costSavingsAnnual = str(rec(projectedSavings.costSavingsAnnual).value);
816
+ if (totalAnnualCost || blendedRate) {
817
+ lines.push('## Labor Cost Analysis', '');
818
+ if (blendedRate)
819
+ lines.push(`- **Avg. fully-loaded rate:** ${blendedRate}`);
820
+ if (totalAnnualCost)
821
+ lines.push(`- **Annual labor cost:** ${totalAnnualCost}`);
822
+ if (totalAnnualHours)
823
+ lines.push(`- **Annual hours affected:** ${totalAnnualHours}`);
824
+ if (costSavingsAnnual)
825
+ lines.push(`- **Automation savings:** ${costSavingsAnnual}`);
826
+ lines.push('');
827
+ }
828
+ // Cost breakdown (each field is { value, notes?, source? })
829
+ const costBreakdown = rec(qROI.costBreakdown);
830
+ const cbImpl = str(rec(costBreakdown.implementation).value);
831
+ const cbLic = str(rec(costBreakdown.annualLicensing).value);
832
+ const cbSupport = str(rec(costBreakdown.annualSupportMaintenance).value);
833
+ if (cbImpl || cbLic) {
834
+ lines.push('## Cost Breakdown', '');
835
+ if (cbImpl)
836
+ lines.push(`- **Implementation:** ${cbImpl}`);
837
+ if (cbLic)
838
+ lines.push(`- **Annual licensing:** ${cbLic}`);
839
+ if (cbSupport)
840
+ lines.push(`- **Annual support/maintenance:** ${cbSupport}`);
841
+ lines.push('');
842
+ }
843
+ // Pilot ROI (nested: pilotCapex/pilotOpex/pilotAnnualSavings/pilotYear1Net are { value, calculation })
844
+ const pilotROI = rec(qROI.pilotROI);
845
+ const pilotCapex = str(rec(pilotROI.pilotCapex).value);
846
+ const pilotOpex = str(rec(pilotROI.pilotOpex).value);
847
+ const pilotSavings = str(rec(pilotROI.pilotAnnualSavings).value);
848
+ const pilotYear1Net = str(rec(pilotROI.pilotYear1Net).value);
849
+ const pilotPayback = numStr(pilotROI.pilotPaybackMonths);
850
+ const pilotSuppressed = pilotROI.suppressed === true || pilotROI.suppressed === 'true';
851
+ if (!pilotSuppressed && (pilotCapex || pilotSavings)) {
852
+ lines.push('## Pilot Economics', '');
853
+ if (pilotCapex)
854
+ lines.push(`- **Pilot capex:** ${pilotCapex}`);
855
+ if (pilotOpex)
856
+ lines.push(`- **Pilot opex:** ${pilotOpex}`);
857
+ if (pilotSavings)
858
+ lines.push(`- **Pilot annual savings:** ${pilotSavings}`);
859
+ if (pilotYear1Net)
860
+ lines.push(`- **Pilot Year 1 net:** ${pilotYear1Net}`);
861
+ if (pilotPayback)
862
+ lines.push(`- **Payback:** ${stripTrailingUnit(pilotPayback, 'months')} months`);
863
+ lines.push('');
864
+ }
865
+ // Sensitivity analysis (roiPercentage, paybackMonths, annualSavings — all numbers/strings)
866
+ const sensitivity = rec(qROI.sensitivity);
867
+ if (sensitivity.conservative || sensitivity.realistic || sensitivity.optimistic) {
868
+ lines.push('## Sensitivity Analysis', '');
869
+ lines.push('| Scenario | ROI | Payback | Annual Savings |');
870
+ lines.push('|----------|-----|---------|----------------|');
871
+ for (const [label, key] of [['Conservative', 'conservative'], ['Realistic', 'realistic'], ['Optimistic', 'optimistic']]) {
872
+ const s = rec(sensitivity[key]);
873
+ const roi = numStr(s.roiPercentage);
874
+ const payback = numStr(s.paybackMonths);
875
+ lines.push(`| ${label} | ${roi ? stripTrailingUnit(roi, '%') + '%' : ''} | ${payback ? stripTrailingUnit(payback, 'months') + ' months' : ''} | ${str(s.annualSavings)} |`);
876
+ }
877
+ lines.push('');
878
+ }
879
+ // 5-year projection (calculator uses costsThisYear/valueDelivered/netThisYear/runningTotal)
880
+ const fiveYear = arr(qROI.fiveYearProjection);
881
+ if (fiveYear.length > 0) {
882
+ lines.push('## Five-Year Projection', '');
883
+ lines.push('| Year | Investment | Value | Net Cash Flow | Cumulative |');
884
+ lines.push('|------|-----------|-------|---------------|------------|');
885
+ for (const yr of fiveYear) {
886
+ const y = rec(yr);
887
+ lines.push(`| ${numStr(y.year)} | ${str(y.costsThisYear) || str(y.investment)} | ${str(y.valueDelivered) || str(y.value)} | ${str(y.netThisYear) || str(y.netCashFlow)} | ${str(y.runningTotal) || str(y.cumulative)} |`);
888
+ }
889
+ lines.push('');
890
+ }
891
+ const tangible = rec(benefits.tangibleBenefits);
892
+ if (str(tangible.costSavings) || str(tangible.processEfficiency)) {
893
+ lines.push('## Tangible Benefits', '');
894
+ if (str(tangible.costSavings))
895
+ lines.push(`- **Cost savings:** ${str(tangible.costSavings)}`);
896
+ if (str(tangible.revenueUplift))
897
+ lines.push(`- **Revenue uplift:** ${str(tangible.revenueUplift)}`);
898
+ if (str(tangible.processEfficiency))
899
+ lines.push(`- **Process efficiency:** ${str(tangible.processEfficiency)}`);
900
+ if (str(tangible.timeToMarket))
901
+ lines.push(`- **Time to market:** ${str(tangible.timeToMarket)}`);
902
+ lines.push('');
903
+ }
904
+ // Recommendation
905
+ const recommendation = rec(bc.recommendation);
906
+ if (str(recommendation.summary) || str(recommendation.decisionRequest)) {
907
+ lines.push('## Recommendation', '');
908
+ if (str(recommendation.summary))
909
+ lines.push(str(recommendation.summary), '');
910
+ if (str(recommendation.decisionRequest)) {
911
+ lines.push(`**Decision request:** ${str(recommendation.decisionRequest)}`, '');
912
+ }
913
+ const immediateActions = arr(recommendation.immediateActions);
914
+ if (immediateActions.length > 0) {
915
+ lines.push('**Immediate actions upon approval:**', '');
916
+ for (const action of immediateActions)
917
+ lines.push(`1. ${action}`);
918
+ lines.push('');
919
+ }
920
+ if (str(recommendation.blueprintImplementationRef)) {
921
+ lines.push(`> ${str(recommendation.blueprintImplementationRef)}`, '');
922
+ }
923
+ }
924
+ return lines.join('\n');
925
+ }
926
+ function buildImplementationRoadmap(input) {
927
+ const ip = input.implementationPlanData;
928
+ const lines = ['# Implementation Roadmap', ''];
929
+ if (!ip) {
930
+ lines.push('_No implementation plan data available. Generate an Implementation Plan to enrich this section._', '');
931
+ return lines.join('\n');
932
+ }
933
+ const overview = rec(ip.projectOverview);
934
+ if (str(overview.projectName)) {
935
+ lines.push(`## ${str(overview.projectName)}`, '');
936
+ }
937
+ if (str(overview.executiveSummary)) {
938
+ lines.push(str(overview.executiveSummary), '');
939
+ }
940
+ if (str(overview.scope)) {
941
+ lines.push('### Scope', '', str(overview.scope), '');
942
+ }
943
+ const assumptions = arr(overview.assumptions);
944
+ if (assumptions.length > 0) {
945
+ lines.push('### Assumptions', '');
946
+ for (const a of assumptions)
947
+ lines.push(`- ${a}`);
948
+ lines.push('');
949
+ }
950
+ const epics = arr(ip.epics);
951
+ if (epics.length > 0) {
952
+ lines.push('## Epics', '');
953
+ for (const epic of epics) {
954
+ const e = rec(epic);
955
+ lines.push(`### ${str(e.name)}`, '');
956
+ if (str(e.description))
957
+ lines.push(str(e.description), '');
958
+ lines.push(`- **Phase:** ${str(e.phase)}`);
959
+ lines.push(`- **Priority:** ${str(e.priority)}`);
960
+ if (str(e.estimatedDuration))
961
+ lines.push(`- **Duration:** ${str(e.estimatedDuration)}`);
962
+ if (str(e.businessValue))
963
+ lines.push(`- **Business value:** ${str(e.businessValue)}`);
964
+ lines.push('');
965
+ const ac = arr(e.acceptanceCriteria);
966
+ if (ac.length > 0) {
967
+ lines.push('**Acceptance criteria:**', '');
968
+ for (const c of ac)
969
+ lines.push(`- [ ] ${c}`);
970
+ lines.push('');
971
+ }
972
+ const stories = arr(e.stories);
973
+ if (stories.length > 0) {
974
+ lines.push('**User stories:**', '');
975
+ for (const story of stories) {
976
+ const s = rec(story);
977
+ const userStory = `As ${str(s.asA)}, I want ${str(s.iWant)}, so that ${str(s.soThat)}`;
978
+ lines.push(`- **${str(s.title)}**: ${userStory}`);
979
+ if (str(s.estimatedEffort))
980
+ lines.push(` - Effort: ${str(s.estimatedEffort)}`);
981
+ }
982
+ lines.push('');
983
+ }
984
+ const deps = arr(e.dependencies);
985
+ if (deps.length > 0) {
986
+ lines.push('**Dependencies:**', '');
987
+ for (const d of deps)
988
+ lines.push(`- ${d}`);
989
+ lines.push('');
990
+ }
991
+ }
992
+ }
993
+ const agentSpecs = arr(ip.agentSpecifications);
994
+ if (agentSpecs.length > 0) {
995
+ lines.push('## Agent Build Specifications', '');
996
+ for (const spec of agentSpecs) {
997
+ const s = rec(spec);
998
+ lines.push(`### ${str(s.name)}`, '');
999
+ if (str(s.role))
1000
+ lines.push(str(s.role), '');
1001
+ if (str(s.instructions))
1002
+ lines.push('**Instructions:**', '', str(s.instructions), '');
1003
+ if (str(s.linkedStoryId))
1004
+ lines.push(`_Linked to story: ${str(s.linkedStoryId)}_`, '');
1005
+ }
1006
+ }
1007
+ const resources = rec(ip.resources);
1008
+ const timeline = rec(resources.timeline);
1009
+ if (str(timeline.totalDuration)) {
1010
+ lines.push('## Timeline', '');
1011
+ lines.push(`**Total duration:** ${str(timeline.totalDuration)}`, '');
1012
+ const timelinePhases = arr(timeline.phases);
1013
+ if (timelinePhases.length > 0) {
1014
+ for (const phase of timelinePhases) {
1015
+ const p = rec(phase);
1016
+ lines.push(`### ${str(p.name)} (${str(p.duration)})`, '');
1017
+ for (const m of arr(p.milestones))
1018
+ lines.push(`- ${m}`);
1019
+ lines.push('');
1020
+ }
1021
+ }
1022
+ }
1023
+ const roles = arr(resources.roles);
1024
+ if (roles.length > 0) {
1025
+ lines.push('## Required Roles', '');
1026
+ lines.push('| Role | Allocation | Duration | Key Skills |');
1027
+ lines.push('|------|-----------|----------|------------|');
1028
+ for (const role of roles) {
1029
+ const r = rec(role);
1030
+ const skills = arr(r.skillsRequired).slice(0, 3).join(', ');
1031
+ lines.push(`| ${str(r.role)} | ${str(r.allocation)} | ${str(r.duration)} | ${skills} |`);
1032
+ }
1033
+ lines.push('');
1034
+ }
1035
+ const deps = arr(ip.dependencies);
1036
+ if (deps.length > 0) {
1037
+ lines.push('## Dependencies', '');
1038
+ for (const dep of deps) {
1039
+ const d = rec(dep);
1040
+ lines.push(`- **${str(d.type)}** (${str(d.criticality)}): ${str(d.description)}`);
1041
+ }
1042
+ lines.push('');
1043
+ }
1044
+ return lines.join('\n');
1045
+ }
1046
+ function buildArchitectureDecisions(input) {
1047
+ const bp = input.blueprintData;
1048
+ const lines = ['# Architecture Decisions', ''];
1049
+ const pr = rec(bp.platformRecommendation);
1050
+ const pp = rec(pr.primaryPlatform);
1051
+ if (str(pp.name)) {
1052
+ lines.push(`## Platform: ${str(pp.name)}`, '');
1053
+ if (str(pp.summary))
1054
+ lines.push(str(pp.summary), '');
1055
+ if (str(pp.justification))
1056
+ lines.push(`**Justification:** ${str(pp.justification)}`, '');
1057
+ const pros = arr(pp.pros);
1058
+ if (pros.length > 0) {
1059
+ lines.push('**Pros:**', '');
1060
+ for (const p of pros)
1061
+ lines.push(`- ${p}`);
1062
+ lines.push('');
1063
+ }
1064
+ const cons = arr(pp.cons);
1065
+ if (cons.length > 0) {
1066
+ lines.push('**Cons:**', '');
1067
+ for (const c of cons)
1068
+ lines.push(`- ${c}`);
1069
+ lines.push('');
1070
+ }
1071
+ if (str(pp.implementationTime))
1072
+ lines.push(`**Implementation time:** ${str(pp.implementationTime)}`);
1073
+ if (str(pp.estimatedCost))
1074
+ lines.push(`**Estimated cost:** ${str(pp.estimatedCost)}`);
1075
+ if (str(pp.integrationComplexity))
1076
+ lines.push(`**Integration complexity:** ${str(pp.integrationComplexity)}`);
1077
+ lines.push('');
1078
+ }
1079
+ const rationale = rec(bp.architectureRationale);
1080
+ const whyAgentic = arr(rationale.whyAgentic);
1081
+ if (whyAgentic.length > 0) {
1082
+ lines.push('## Why Agentic AI', '');
1083
+ for (const w of whyAgentic)
1084
+ lines.push(`- ${w}`);
1085
+ lines.push('');
1086
+ }
1087
+ const hybrid = arr(rationale.hybridComponents);
1088
+ if (hybrid.length > 0) {
1089
+ lines.push('## Hybrid Components', '');
1090
+ lines.push('| Component | Approach | Rationale |');
1091
+ lines.push('|-----------|----------|-----------|');
1092
+ for (const h of hybrid) {
1093
+ const hr = rec(h);
1094
+ lines.push(`| ${str(hr.component)} | ${str(hr.approach)} | ${str(hr.rationale)} |`);
1095
+ }
1096
+ lines.push('');
1097
+ }
1098
+ const wins = arr(rationale.immediateWins);
1099
+ if (wins.length > 0) {
1100
+ lines.push('## Immediate Wins', '');
1101
+ for (const w of wins)
1102
+ lines.push(`- ${w}`);
1103
+ lines.push('');
1104
+ }
1105
+ const reasoning = rec(bp.reasoning);
1106
+ const bizDecisions = rec(reasoning.businessDecisions);
1107
+ const patternSelection = rec(bizDecisions.patternSelection);
1108
+ if (str(patternSelection.decision)) {
1109
+ lines.push('## Pattern Selection', '');
1110
+ lines.push(`**Selected:** ${str(patternSelection.decision)}`);
1111
+ if (str(patternSelection.rationale))
1112
+ lines.push(`**Rationale:** ${str(patternSelection.rationale)}`);
1113
+ if (str(patternSelection.reasoning))
1114
+ lines.push(`**Business factors:** ${str(patternSelection.reasoning)}`);
1115
+ const alts = arr(patternSelection.alternatives);
1116
+ if (alts.length > 0)
1117
+ lines.push(`**Alternatives considered:** ${alts.join(', ')}`);
1118
+ lines.push('');
1119
+ }
1120
+ const gaps = arr(bp.integrationGaps);
1121
+ if (gaps.length > 0) {
1122
+ lines.push('## Integration Gaps', '');
1123
+ lines.push('| System | Gap Type | Severity | Impact | Recommendation |');
1124
+ lines.push('|--------|----------|----------|--------|----------------|');
1125
+ for (const gap of gaps) {
1126
+ const g = rec(gap);
1127
+ lines.push(`| ${str(g.systemNeeded)} | ${str(g.gapType)} | ${str(g.severity)} | ${str(g.impact)} | ${str(g.recommendation)} |`);
1128
+ }
1129
+ lines.push('');
1130
+ }
1131
+ const altPlatforms = arr(pr.alternativePlatforms);
1132
+ if (altPlatforms.length > 0) {
1133
+ lines.push('## Alternative Platforms Considered', '');
1134
+ for (const alt of altPlatforms) {
1135
+ const a = rec(alt);
1136
+ lines.push(`### ${str(a.name)}`, '');
1137
+ if (str(a.justification))
1138
+ lines.push(str(a.justification), '');
1139
+ if (str(a.estimatedCost))
1140
+ lines.push(`- **Cost:** ${str(a.estimatedCost)}`);
1141
+ if (str(a.implementationTime))
1142
+ lines.push(`- **Timeline:** ${str(a.implementationTime)}`);
1143
+ if (str(a.integrationComplexity))
1144
+ lines.push(`- **Complexity:** ${str(a.integrationComplexity)}`);
1145
+ lines.push('');
1146
+ }
1147
+ }
1148
+ const feasibility = rec(bp.feasibilityIndicators);
1149
+ const feasConfidence = str(feasibility.feasibilityConfidence) || str(feasibility.overallScore);
1150
+ const feasBasis = str(feasibility.feasibilityBasis) || str(feasibility.recommendation);
1151
+ if (feasConfidence || feasBasis) {
1152
+ lines.push('## Feasibility Assessment', '');
1153
+ if (feasConfidence)
1154
+ lines.push(`**Confidence:** ${feasConfidence}`);
1155
+ if (feasBasis)
1156
+ lines.push(`**Basis:** ${feasBasis}`);
1157
+ lines.push('');
1158
+ }
1159
+ return lines.join('\n');
1160
+ }
1161
+ function buildGuardrailsAndGovernance(input) {
1162
+ const bp = input.blueprintData;
1163
+ const bc = input.businessCaseData;
1164
+ const team = getTeam(bp);
1165
+ const lines = ['# Guardrails & Governance', ''];
1166
+ const riskAssessment = rec(bp.riskAssessment);
1167
+ const techRisks = arr(riskAssessment.technicalRisks);
1168
+ const bizRisks = arr(riskAssessment.businessRisks);
1169
+ const mitStrategies = arr(riskAssessment.mitigationStrategies);
1170
+ const contingencies = arr(riskAssessment.contingencyPlans);
1171
+ if (techRisks.length > 0) {
1172
+ lines.push('## Technical Risks', '');
1173
+ for (const r of techRisks)
1174
+ lines.push(`- ${r}`);
1175
+ lines.push('');
1176
+ }
1177
+ if (bizRisks.length > 0) {
1178
+ lines.push('## Business Risks', '');
1179
+ for (const r of bizRisks)
1180
+ lines.push(`- ${r}`);
1181
+ lines.push('');
1182
+ }
1183
+ if (mitStrategies.length > 0) {
1184
+ lines.push('## Mitigation Strategies', '');
1185
+ for (const m of mitStrategies)
1186
+ lines.push(`- ${m}`);
1187
+ lines.push('');
1188
+ }
1189
+ if (contingencies.length > 0) {
1190
+ lines.push('## Contingency Plans', '');
1191
+ for (const c of contingencies)
1192
+ lines.push(`- ${c}`);
1193
+ lines.push('');
1194
+ }
1195
+ const agentsWithGuardrails = team.filter(a => arr(a.guardrails).length > 0 || arr(a.escalationRules).length > 0);
1196
+ if (agentsWithGuardrails.length > 0) {
1197
+ lines.push('## Agent-Level Guardrails', '');
1198
+ for (const agent of agentsWithGuardrails) {
1199
+ lines.push(`### ${str(agent.name)}`, '');
1200
+ const guardrails = arr(agent.guardrails);
1201
+ if (guardrails.length > 0) {
1202
+ lines.push('**Guardrails:**', '');
1203
+ for (const g of guardrails) {
1204
+ const gr = rec(g);
1205
+ lines.push(`- **${str(gr.type)}**: ${str(gr.condition) || str(gr.description)}`);
1206
+ }
1207
+ lines.push('');
1208
+ }
1209
+ const escalation = arr(agent.escalationRules);
1210
+ if (escalation.length > 0) {
1211
+ lines.push('**Escalation rules:**', '');
1212
+ for (const rule of escalation)
1213
+ lines.push(`- ${rule}`);
1214
+ lines.push('');
1215
+ }
1216
+ const risk = rec(agent.riskAssessment);
1217
+ if (str(risk.level) && !isPlaceholder(str(risk.level))) {
1218
+ const impactStr = str(risk.impact);
1219
+ const riskLine = impactStr && !isPlaceholder(impactStr)
1220
+ ? `**Risk:** ${str(risk.level)} — ${impactStr}`
1221
+ : `**Risk:** ${str(risk.level)}`;
1222
+ lines.push(riskLine);
1223
+ lines.push('');
1224
+ }
1225
+ }
1226
+ }
1227
+ if (bc) {
1228
+ const bcRisks = rec(bc.risks);
1229
+ const implRisks = arr(bcRisks.implementationRisks);
1230
+ const opRisks = arr(bcRisks.operationalRisks);
1231
+ const mitigationPlan = arr(bcRisks.mitigationPlan);
1232
+ if (implRisks.length > 0) {
1233
+ lines.push('## Implementation Risks (Business Case)', '');
1234
+ lines.push('| Risk | Severity | Impact |');
1235
+ lines.push('|------|----------|--------|');
1236
+ for (const risk of implRisks) {
1237
+ const r = rec(risk);
1238
+ lines.push(`| ${str(r.title)} | ${str(r.severity)} | ${str(r.impact)} |`);
1239
+ }
1240
+ lines.push('');
1241
+ }
1242
+ if (opRisks.length > 0) {
1243
+ lines.push('## Operational Risks (Business Case)', '');
1244
+ lines.push('| Risk | Severity | Impact |');
1245
+ lines.push('|------|----------|--------|');
1246
+ for (const risk of opRisks) {
1247
+ const r = rec(risk);
1248
+ lines.push(`| ${str(r.title)} | ${str(r.severity)} | ${str(r.impact)} |`);
1249
+ }
1250
+ lines.push('');
1251
+ }
1252
+ if (mitigationPlan.length > 0) {
1253
+ lines.push('## Mitigation Plan', '');
1254
+ for (const mit of mitigationPlan) {
1255
+ const m = rec(mit);
1256
+ lines.push(`### ${str(m.riskTitle)}`, '');
1257
+ lines.push(`- **Strategy:** ${str(m.strategy)}`);
1258
+ if (str(m.owner))
1259
+ lines.push(`- **Owner:** ${str(m.owner)}`);
1260
+ if (str(m.timeline))
1261
+ lines.push(`- **Timeline:** ${str(m.timeline)}`);
1262
+ lines.push('');
1263
+ }
1264
+ }
1265
+ }
1266
+ return lines.join('\n');
1267
+ }
1268
+ function normalizeMetricName(name) {
1269
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
1270
+ }
1271
+ function buildEvaluationCriteria(input) {
1272
+ const { blueprintData, businessCaseData } = input;
1273
+ const bp = rec(blueprintData);
1274
+ const bc = rec(businessCaseData);
1275
+ const lines = [
1276
+ '# Evaluation Criteria',
1277
+ '',
1278
+ '> Machine-readable success metrics for deployment monitoring.',
1279
+ '> Map these criteria to your monitoring system to track agent performance.',
1280
+ '',
1281
+ ];
1282
+ const roiBaseline = rec(bp.roiBaseline);
1283
+ const roiOps = arr(roiBaseline.operational);
1284
+ const roiFin = arr(roiBaseline.financial);
1285
+ const objectives = rec(bc.objectives);
1286
+ const successMetrics = arr(objectives.successMetrics);
1287
+ const successMetricsByName = new Map();
1288
+ for (const sm of successMetrics) {
1289
+ const m = rec(sm);
1290
+ const key = normalizeMetricName(str(m.metric));
1291
+ if (key)
1292
+ successMetricsByName.set(key, m);
1293
+ }
1294
+ const kpis = arr(rec(bp.successCriteria).kpis);
1295
+ const quantifiedROI = rec(rec(bc.benefits).quantifiedROI);
1296
+ const team = arr(bp.enhancedDigitalTeam);
1297
+ let hasContent = false;
1298
+ // --- Operational Metrics ---
1299
+ const operationalRows = [];
1300
+ if (roiOps.length > 0) {
1301
+ for (const item of roiOps) {
1302
+ const m = rec(item);
1303
+ const name = str(m.name);
1304
+ const enrichment = successMetricsByName.get(normalizeMetricName(name));
1305
+ const baseline = enrichment ? str(rec(enrichment).currentValue) : '';
1306
+ const frequency = enrichment ? str(rec(enrichment).measurementFrequency) : '';
1307
+ operationalRows.push(`| ${name} | ${baseline || '-'} | ${str(m.predictedValue)} | ${str(m.direction) || '-'} | ${str(m.unit) || '-'} | ${frequency || '-'} | ${str(m.source)} |`);
1308
+ }
1309
+ }
1310
+ else if (successMetrics.length > 0) {
1311
+ for (const item of successMetrics) {
1312
+ const m = rec(item);
1313
+ operationalRows.push(`| ${str(m.metric)} | ${str(m.currentValue) || '-'} | ${str(m.targetValue)} | ${str(m.direction) || '-'} | ${str(m.unit) || '-'} | ${str(m.measurementFrequency) || '-'} | businessCase.objectives |`);
1314
+ }
1315
+ }
1316
+ else if (kpis.length > 0) {
1317
+ for (const item of kpis) {
1318
+ const m = rec(item);
1319
+ operationalRows.push(`| ${str(m.name)} | - | ${str(m.target)} | - | ${str(m.unit) || '-'} | - | successCriteria.kpis |`);
1320
+ }
1321
+ }
1322
+ if (operationalRows.length > 0) {
1323
+ hasContent = true;
1324
+ lines.push('## Operational Metrics', '', '| Metric | Baseline | Target | Direction | Unit | Frequency | Source |', '|--------|----------|--------|-----------|------|-----------|--------|', ...operationalRows, '');
1325
+ }
1326
+ // --- Financial Metrics ---
1327
+ const financialRows = [];
1328
+ if (roiFin.length > 0) {
1329
+ for (const item of roiFin) {
1330
+ const m = rec(item);
1331
+ financialRows.push(`| ${str(m.name)} | ${str(m.predictedValue)} | ${str(m.direction) || '-'} | ${str(m.unit) || '-'} | ${str(m.source)} |`);
1332
+ }
1333
+ }
1334
+ else {
1335
+ if (str(quantifiedROI.roi)) {
1336
+ financialRows.push(`| ROI | ${str(quantifiedROI.roi)} | higher_is_better | % | quantifiedROI |`);
1337
+ }
1338
+ if (str(quantifiedROI.paybackPeriod)) {
1339
+ financialRows.push(`| Payback Period | ${str(quantifiedROI.paybackPeriod)} | lower_is_better | months | quantifiedROI |`);
1340
+ }
1341
+ if (str(quantifiedROI.npv)) {
1342
+ financialRows.push(`| NPV | ${str(quantifiedROI.npv)} | higher_is_better | currency | quantifiedROI |`);
1343
+ }
1344
+ const annualSavings = str(rec(rec(quantifiedROI.laborCostDetail).projectedSavings).costSavingsAnnual);
1345
+ if (annualSavings) {
1346
+ financialRows.push(`| Annual Cost Savings | ${annualSavings} | higher_is_better | currency | quantifiedROI |`);
1347
+ }
1348
+ }
1349
+ if (financialRows.length > 0) {
1350
+ hasContent = true;
1351
+ lines.push('## Financial Metrics', '', '| Metric | Target | Direction | Unit | Source |', '|--------|--------|-----------|------|--------|', ...financialRows, '');
1352
+ }
1353
+ // --- Agent-Level Metrics ---
1354
+ const agentRows = [];
1355
+ for (const agent of team) {
1356
+ const a = rec(agent);
1357
+ const metrics = arr(a.successMetrics);
1358
+ for (const item of metrics) {
1359
+ const m = rec(item);
1360
+ agentRows.push(`| ${str(a.name)} | ${str(m.metric)} | ${str(m.target)} |`);
1361
+ }
1362
+ }
1363
+ if (agentRows.length > 0) {
1364
+ hasContent = true;
1365
+ lines.push('## Agent-Level Metrics', '', '| Agent | Metric | Target |', '|-------|--------|--------|', ...agentRows, '');
1366
+ }
1367
+ if (!hasContent) {
1368
+ lines.push('> No evaluation criteria available yet. Generate a Business Case to populate', '> operational and financial metrics, or add success metrics to agent specifications.', '');
1369
+ }
1370
+ // --- Monitoring Guidance ---
1371
+ lines.push('## Monitoring Guidance', '', '> If using Agent Blueprint\'s performance monitoring feature, these criteria can inform metric setup:', '> - Operational metrics correspond to `metricType: "operational"`', '> - Financial metrics correspond to `metricType: "financial"`', '> - Use metric names and targets when recording actuals via the Performance tab or webhook integrations', '');
1372
+ return lines.join('\n');
1373
+ }
1374
+ function buildValidateScript() {
1375
+ return `#!/bin/bash
1376
+ # validate-spec.sh — Validates implementation spec structure completeness
1377
+ # Usage: ./scripts/validate-spec.sh
1378
+
1379
+ set -e
1380
+
1381
+ ERRORS=0
1382
+ WARNINGS=0
1383
+
1384
+ check_file() {
1385
+ if [ ! -f "$1" ]; then
1386
+ echo "ERROR: Missing required file: $1"
1387
+ ERRORS=$((ERRORS + 1))
1388
+ else
1389
+ echo "OK: $1"
1390
+ fi
1391
+ }
1392
+
1393
+ check_optional() {
1394
+ if [ ! -f "$1" ]; then
1395
+ echo "WARN: Optional file missing: $1 (consider generating the missing artifact)"
1396
+ WARNINGS=$((WARNINGS + 1))
1397
+ else
1398
+ echo "OK: $1"
1399
+ fi
1400
+ }
1401
+
1402
+ echo "=== Implementation Spec Validator ==="
1403
+ echo ""
1404
+
1405
+ # Required files
1406
+ echo "--- Required Files ---"
1407
+ check_file "SKILL.md"
1408
+ check_file "references/agent-specifications.md"
1409
+ check_file "references/architecture-decisions.md"
1410
+
1411
+ # Check SKILL.md has frontmatter
1412
+ if [ -f "SKILL.md" ]; then
1413
+ if ! head -1 SKILL.md | grep -q "^---"; then
1414
+ echo "ERROR: SKILL.md missing YAML frontmatter"
1415
+ ERRORS=$((ERRORS + 1))
1416
+ fi
1417
+ fi
1418
+
1419
+ echo ""
1420
+ echo "--- Optional Files ---"
1421
+ check_optional "references/business-context.md"
1422
+ check_optional "references/organization-context.md"
1423
+ check_optional "references/financial-case.md"
1424
+ check_optional "references/implementation-roadmap.md"
1425
+ check_optional "references/guardrails-and-governance.md"
1426
+ check_optional "references/evaluation-criteria.md"
1427
+
1428
+ echo ""
1429
+ echo "=== Results ==="
1430
+ echo "Errors: $ERRORS"
1431
+ echo "Warnings: $WARNINGS"
1432
+
1433
+ if [ $ERRORS -gt 0 ]; then
1434
+ echo "FAILED: Fix $ERRORS error(s) before proceeding."
1435
+ exit 1
1436
+ else
1437
+ echo "PASSED"
1438
+ exit 0
1439
+ fi
1440
+ `;
1441
+ }
1442
+ // =============================================================================
1443
+ // MAIN RENDER FUNCTION
1444
+ // =============================================================================
1445
+ /**
1446
+ * Renders a complete Agent Skills directory from blueprint data.
1447
+ * Returns a Map of { relativePath → fileContent }.
1448
+ */
1449
+ export function renderSkillDirectory(input) {
1450
+ const files = new Map();
1451
+ // SKILL.md
1452
+ const frontmatter = buildSkillFrontmatter(input);
1453
+ const body = buildSkillBody(input);
1454
+ files.set('SKILL.md', `${frontmatter}\n\n${body}`);
1455
+ // Reference files
1456
+ files.set('references/business-context.md', buildBusinessContext(input));
1457
+ files.set('references/organization-context.md', buildOrganizationContext(input));
1458
+ files.set('references/agent-specifications.md', buildAgentSpecifications(input));
1459
+ files.set('references/financial-case.md', buildFinancialCase(input));
1460
+ files.set('references/implementation-roadmap.md', buildImplementationRoadmap(input));
1461
+ files.set('references/architecture-decisions.md', buildArchitectureDecisions(input));
1462
+ files.set('references/guardrails-and-governance.md', buildGuardrailsAndGovernance(input));
1463
+ files.set('references/evaluation-criteria.md', buildEvaluationCriteria(input));
1464
+ // Scripts
1465
+ files.set('scripts/validate-spec.sh', buildValidateScript());
1466
+ return files;
1467
+ }
1468
+ //# sourceMappingURL=renderers.js.map