agentblueprint 0.6.26 → 0.6.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/renderers.test.js +143 -85
- package/dist/__tests__/renderers.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +2 -2
- package/dist/fetch-blueprint.js +1 -3
- package/dist/fetch-blueprint.js.map +1 -1
- package/dist/renderers.d.ts +0 -1
- package/dist/renderers.js +213 -268
- package/dist/renderers.js.map +1 -1
- package/package.json +1 -1
package/dist/renderers.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export interface SkillRenderInput {
|
|
|
9
9
|
organizationName?: string;
|
|
10
10
|
blueprintData: Record<string, unknown>;
|
|
11
11
|
businessCaseData?: Record<string, unknown>;
|
|
12
|
-
implementationPlanData?: Record<string, unknown>;
|
|
13
12
|
useCaseData?: Record<string, unknown>;
|
|
14
13
|
businessProfileData?: Record<string, unknown>;
|
|
15
14
|
generalGuide?: string;
|
package/dist/renderers.js
CHANGED
|
@@ -189,106 +189,67 @@ function buildSkillBody(input) {
|
|
|
189
189
|
});
|
|
190
190
|
lines.push('');
|
|
191
191
|
lines.push('> Full agent specifications in `references/agent-specifications.md`', '');
|
|
192
|
-
// Phase rendering —
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
192
|
+
// Phase rendering — always uses blueprint phases
|
|
193
|
+
lines.push('## Phase 1: Pilot', '');
|
|
194
|
+
const phases = arr(bp.phases);
|
|
195
|
+
const pilotPhase = phases.find((p) => str(p?.name).toLowerCase().includes('pilot') || str(p?.name).toLowerCase().includes('phase 1'));
|
|
196
|
+
if (pilotPhase) {
|
|
197
|
+
const p = rec(pilotPhase);
|
|
198
|
+
if (str(p.phaseGoal))
|
|
199
|
+
lines.push(`**Goal:** ${str(p.phaseGoal)}`, '');
|
|
200
|
+
if (p.durationWeeks)
|
|
201
|
+
lines.push(`**Duration:** ${p.durationWeeks} weeks`);
|
|
202
|
+
if (str(p.phaseCost))
|
|
203
|
+
lines.push(`**Cost target:** ${str(p.phaseCost)}`);
|
|
204
|
+
lines.push('');
|
|
205
|
+
const workstreams = arr(p.workstreams);
|
|
206
|
+
if (workstreams.length > 0) {
|
|
207
|
+
lines.push('**Pilot workstreams:**', '');
|
|
208
|
+
for (const ws of workstreams) {
|
|
209
|
+
const w = rec(ws);
|
|
210
|
+
lines.push(`- ${str(w.title)}`);
|
|
207
211
|
}
|
|
208
212
|
lines.push('');
|
|
209
213
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const e = rec(epic);
|
|
218
|
-
const name = str(e.name);
|
|
219
|
-
if (name && !seen.has(name)) {
|
|
220
|
-
seen.add(name);
|
|
221
|
-
lines.push(`- **${name}**${str(e.estimatedDuration) ? ` (${str(e.estimatedDuration)})` : ''}`);
|
|
222
|
-
}
|
|
214
|
+
const gate = rec(p.decisionGate);
|
|
215
|
+
if (gate.criteria) {
|
|
216
|
+
lines.push('**Decision gate criteria:**', '');
|
|
217
|
+
for (const c of arr(gate.criteria)) {
|
|
218
|
+
const cr = rec(c);
|
|
219
|
+
const label = str(cr.name) || str(cr.criterion) || str(cr.metric) || str(cr.description) || 'Unnamed criterion';
|
|
220
|
+
lines.push(`- ${label}: ${str(cr.target) || str(cr.threshold)}`);
|
|
223
221
|
}
|
|
224
222
|
lines.push('');
|
|
225
223
|
}
|
|
226
|
-
|
|
227
|
-
|
|
224
|
+
const exitCriteria = arr(p.exitCriteria);
|
|
225
|
+
if (exitCriteria.length > 0) {
|
|
226
|
+
lines.push('**Exit criteria:**', '');
|
|
227
|
+
for (const c of exitCriteria)
|
|
228
|
+
lines.push(`- ${c}`);
|
|
229
|
+
lines.push('');
|
|
228
230
|
}
|
|
229
231
|
}
|
|
230
232
|
else {
|
|
231
|
-
lines.push('
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
lines.push('_No pilot phase defined._', '');
|
|
234
|
+
}
|
|
235
|
+
lines.push('## Phase 2: Full Implementation', '');
|
|
236
|
+
const fullPhases = phases.filter((p) => !str(p?.name).toLowerCase().includes('pilot') && !str(p?.name).toLowerCase().includes('phase 1'));
|
|
237
|
+
if (fullPhases.length > 0) {
|
|
238
|
+
for (const phase of fullPhases) {
|
|
239
|
+
const p = rec(phase);
|
|
240
|
+
lines.push(`### ${str(p.name)}`, '');
|
|
236
241
|
if (str(p.phaseGoal))
|
|
237
|
-
lines.push(
|
|
242
|
+
lines.push(str(p.phaseGoal), '');
|
|
238
243
|
if (p.durationWeeks)
|
|
239
244
|
lines.push(`**Duration:** ${p.durationWeeks} weeks`);
|
|
240
245
|
if (str(p.phaseCost))
|
|
241
|
-
lines.push(`**Cost
|
|
246
|
+
lines.push(`**Cost:** ${str(p.phaseCost)}`);
|
|
242
247
|
lines.push('');
|
|
243
|
-
const workstreams = arr(p.workstreams);
|
|
244
|
-
if (workstreams.length > 0) {
|
|
245
|
-
lines.push('**Pilot workstreams:**', '');
|
|
246
|
-
for (const ws of workstreams) {
|
|
247
|
-
const w = rec(ws);
|
|
248
|
-
lines.push(`- ${str(w.title)}`);
|
|
249
|
-
}
|
|
250
|
-
lines.push('');
|
|
251
|
-
}
|
|
252
|
-
const gate = rec(p.decisionGate);
|
|
253
|
-
if (gate.criteria) {
|
|
254
|
-
lines.push('**Decision gate criteria:**', '');
|
|
255
|
-
for (const c of arr(gate.criteria)) {
|
|
256
|
-
const cr = rec(c);
|
|
257
|
-
const label = str(cr.name) || str(cr.criterion) || str(cr.metric) || str(cr.description) || 'Unnamed criterion';
|
|
258
|
-
lines.push(`- ${label}: ${str(cr.target) || str(cr.threshold)}`);
|
|
259
|
-
}
|
|
260
|
-
lines.push('');
|
|
261
|
-
}
|
|
262
|
-
const exitCriteria = arr(p.exitCriteria);
|
|
263
|
-
if (exitCriteria.length > 0) {
|
|
264
|
-
lines.push('**Exit criteria:**', '');
|
|
265
|
-
for (const c of exitCriteria)
|
|
266
|
-
lines.push(`- ${c}`);
|
|
267
|
-
lines.push('');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
lines.push('_No pilot phase defined. See `references/implementation-roadmap.md` for phasing._', '');
|
|
272
|
-
}
|
|
273
|
-
lines.push('## Phase 2: Full Implementation', '');
|
|
274
|
-
const fullPhases = phases.filter((p) => !str(p?.name).toLowerCase().includes('pilot') && !str(p?.name).toLowerCase().includes('phase 1'));
|
|
275
|
-
if (fullPhases.length > 0) {
|
|
276
|
-
for (const phase of fullPhases) {
|
|
277
|
-
const p = rec(phase);
|
|
278
|
-
lines.push(`### ${str(p.name)}`, '');
|
|
279
|
-
if (str(p.phaseGoal))
|
|
280
|
-
lines.push(str(p.phaseGoal), '');
|
|
281
|
-
if (p.durationWeeks)
|
|
282
|
-
lines.push(`**Duration:** ${p.durationWeeks} weeks`);
|
|
283
|
-
if (str(p.phaseCost))
|
|
284
|
-
lines.push(`**Cost:** ${str(p.phaseCost)}`);
|
|
285
|
-
lines.push('');
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
lines.push('_See `references/implementation-roadmap.md` for full rollout plan._', '');
|
|
290
248
|
}
|
|
291
249
|
}
|
|
250
|
+
else {
|
|
251
|
+
lines.push('_No full rollout phases defined._', '');
|
|
252
|
+
}
|
|
292
253
|
// Financial Summary
|
|
293
254
|
lines.push('## Financial Summary', '');
|
|
294
255
|
if (bc) {
|
|
@@ -949,126 +910,6 @@ function buildFinancialCase(input) {
|
|
|
949
910
|
}
|
|
950
911
|
return lines.join('\n');
|
|
951
912
|
}
|
|
952
|
-
function buildImplementationRoadmap(input) {
|
|
953
|
-
const ip = input.implementationPlanData;
|
|
954
|
-
const lines = ['# Implementation Roadmap', ''];
|
|
955
|
-
if (!ip) {
|
|
956
|
-
lines.push('_No implementation plan data available. Generate an Implementation Plan to enrich this section._', '');
|
|
957
|
-
return lines.join('\n');
|
|
958
|
-
}
|
|
959
|
-
const overview = rec(ip.projectOverview);
|
|
960
|
-
if (str(overview.projectName)) {
|
|
961
|
-
lines.push(`## ${str(overview.projectName)}`, '');
|
|
962
|
-
}
|
|
963
|
-
if (str(overview.executiveSummary)) {
|
|
964
|
-
lines.push(str(overview.executiveSummary), '');
|
|
965
|
-
}
|
|
966
|
-
if (str(overview.scope)) {
|
|
967
|
-
lines.push('### Scope', '', str(overview.scope), '');
|
|
968
|
-
}
|
|
969
|
-
const assumptions = arr(overview.assumptions);
|
|
970
|
-
if (assumptions.length > 0) {
|
|
971
|
-
lines.push('### Assumptions', '');
|
|
972
|
-
for (const a of assumptions)
|
|
973
|
-
lines.push(`- ${a}`);
|
|
974
|
-
lines.push('');
|
|
975
|
-
}
|
|
976
|
-
const epics = arr(ip.epics);
|
|
977
|
-
if (epics.length > 0) {
|
|
978
|
-
lines.push('## Epics', '');
|
|
979
|
-
for (const epic of epics) {
|
|
980
|
-
const e = rec(epic);
|
|
981
|
-
lines.push(`### ${str(e.name)}`, '');
|
|
982
|
-
if (str(e.description))
|
|
983
|
-
lines.push(str(e.description), '');
|
|
984
|
-
lines.push(`- **Phase:** ${str(e.phase)}`);
|
|
985
|
-
lines.push(`- **Priority:** ${str(e.priority)}`);
|
|
986
|
-
if (str(e.estimatedDuration))
|
|
987
|
-
lines.push(`- **Duration:** ${str(e.estimatedDuration)}`);
|
|
988
|
-
if (str(e.businessValue))
|
|
989
|
-
lines.push(`- **Business value:** ${str(e.businessValue)}`);
|
|
990
|
-
lines.push('');
|
|
991
|
-
const ac = arr(e.acceptanceCriteria);
|
|
992
|
-
if (ac.length > 0) {
|
|
993
|
-
lines.push('**Acceptance criteria:**', '');
|
|
994
|
-
for (const c of ac)
|
|
995
|
-
lines.push(`- [ ] ${c}`);
|
|
996
|
-
lines.push('');
|
|
997
|
-
}
|
|
998
|
-
const stories = arr(e.stories);
|
|
999
|
-
if (stories.length > 0) {
|
|
1000
|
-
lines.push('**User stories:**', '');
|
|
1001
|
-
for (const story of stories) {
|
|
1002
|
-
const s = rec(story);
|
|
1003
|
-
const userStory = `As ${str(s.asA)}, I want ${str(s.iWant)}, so that ${str(s.soThat)}`;
|
|
1004
|
-
lines.push(`- **${str(s.title)}**: ${userStory}`);
|
|
1005
|
-
if (str(s.estimatedEffort))
|
|
1006
|
-
lines.push(` - Effort: ${str(s.estimatedEffort)}`);
|
|
1007
|
-
}
|
|
1008
|
-
lines.push('');
|
|
1009
|
-
}
|
|
1010
|
-
const deps = arr(e.dependencies);
|
|
1011
|
-
if (deps.length > 0) {
|
|
1012
|
-
lines.push('**Dependencies:**', '');
|
|
1013
|
-
for (const d of deps)
|
|
1014
|
-
lines.push(`- ${d}`);
|
|
1015
|
-
lines.push('');
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
const agentSpecs = arr(ip.agentSpecifications);
|
|
1020
|
-
if (agentSpecs.length > 0) {
|
|
1021
|
-
lines.push('## Agent Build Specifications', '');
|
|
1022
|
-
for (const spec of agentSpecs) {
|
|
1023
|
-
const s = rec(spec);
|
|
1024
|
-
lines.push(`### ${str(s.name)}`, '');
|
|
1025
|
-
if (str(s.role))
|
|
1026
|
-
lines.push(str(s.role), '');
|
|
1027
|
-
if (str(s.instructions))
|
|
1028
|
-
lines.push('**Instructions:**', '', str(s.instructions), '');
|
|
1029
|
-
if (str(s.linkedStoryId))
|
|
1030
|
-
lines.push(`_Linked to story: ${str(s.linkedStoryId)}_`, '');
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
const resources = rec(ip.resources);
|
|
1034
|
-
const timeline = rec(resources.timeline);
|
|
1035
|
-
if (str(timeline.totalDuration)) {
|
|
1036
|
-
lines.push('## Timeline', '');
|
|
1037
|
-
lines.push(`**Total duration:** ${str(timeline.totalDuration)}`, '');
|
|
1038
|
-
const timelinePhases = arr(timeline.phases);
|
|
1039
|
-
if (timelinePhases.length > 0) {
|
|
1040
|
-
for (const phase of timelinePhases) {
|
|
1041
|
-
const p = rec(phase);
|
|
1042
|
-
lines.push(`### ${str(p.name)} (${str(p.duration)})`, '');
|
|
1043
|
-
for (const m of arr(p.milestones))
|
|
1044
|
-
lines.push(`- ${m}`);
|
|
1045
|
-
lines.push('');
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
const roles = arr(resources.roles);
|
|
1050
|
-
if (roles.length > 0) {
|
|
1051
|
-
lines.push('## Required Roles', '');
|
|
1052
|
-
lines.push('| Role | Allocation | Duration | Key Skills |');
|
|
1053
|
-
lines.push('|------|-----------|----------|------------|');
|
|
1054
|
-
for (const role of roles) {
|
|
1055
|
-
const r = rec(role);
|
|
1056
|
-
const skills = arr(r.skillsRequired).slice(0, 3).join(', ');
|
|
1057
|
-
lines.push(`| ${str(r.role)} | ${str(r.allocation)} | ${str(r.duration)} | ${skills} |`);
|
|
1058
|
-
}
|
|
1059
|
-
lines.push('');
|
|
1060
|
-
}
|
|
1061
|
-
const deps = arr(ip.dependencies);
|
|
1062
|
-
if (deps.length > 0) {
|
|
1063
|
-
lines.push('## Dependencies', '');
|
|
1064
|
-
for (const dep of deps) {
|
|
1065
|
-
const d = rec(dep);
|
|
1066
|
-
lines.push(`- **${str(d.type)}** (${str(d.criticality)}): ${str(d.description)}`);
|
|
1067
|
-
}
|
|
1068
|
-
lines.push('');
|
|
1069
|
-
}
|
|
1070
|
-
return lines.join('\n');
|
|
1071
|
-
}
|
|
1072
913
|
function buildArchitectureDecisions(input) {
|
|
1073
914
|
const bp = input.blueprintData;
|
|
1074
915
|
const lines = ['# Architecture Decisions', ''];
|
|
@@ -1438,54 +1279,10 @@ function buildRecommendations(input) {
|
|
|
1438
1279
|
const bp = rec(input.blueprintData);
|
|
1439
1280
|
const team = arr(bp.enhancedDigitalTeam);
|
|
1440
1281
|
const bc = rec(input.businessCaseData);
|
|
1441
|
-
// Build epic lookup for priority ordering
|
|
1442
|
-
const epics = arr(rec(input.implementationPlanData).epics);
|
|
1443
|
-
const epicByNormalizedName = new Map();
|
|
1444
|
-
for (const e of epics) {
|
|
1445
|
-
const epic = rec(e);
|
|
1446
|
-
const name = str(epic.name).toLowerCase().trim();
|
|
1447
|
-
epicByNormalizedName.set(name, {
|
|
1448
|
-
phase: str(epic.phase),
|
|
1449
|
-
priority: str(epic.priority) || 'P2',
|
|
1450
|
-
dependencies: arr(epic.dependencies).map((d) => typeof d === 'string' ? d : str(rec(d).description) || str(d)),
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
// Helper to find the best-matching epic for an agent
|
|
1454
|
-
function findEpicForAgent(agentName) {
|
|
1455
|
-
const norm = agentName.toLowerCase().trim();
|
|
1456
|
-
// Direct match
|
|
1457
|
-
for (const [epicName, epic] of epicByNormalizedName) {
|
|
1458
|
-
if (epicName.includes(norm) || norm.includes(epicName))
|
|
1459
|
-
return epic;
|
|
1460
|
-
}
|
|
1461
|
-
// Word overlap
|
|
1462
|
-
const agentWords = norm.split(/\s+/).filter(w => w.length > 2);
|
|
1463
|
-
for (const [epicName, epic] of epicByNormalizedName) {
|
|
1464
|
-
for (const word of agentWords) {
|
|
1465
|
-
if (epicName.includes(word))
|
|
1466
|
-
return epic;
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
return undefined;
|
|
1470
|
-
}
|
|
1471
|
-
// Priority sort key: P0=0, P1=1, P2=2, unknown=3
|
|
1472
|
-
function priorityKey(p) {
|
|
1473
|
-
if (p === 'P0')
|
|
1474
|
-
return 0;
|
|
1475
|
-
if (p === 'P1')
|
|
1476
|
-
return 1;
|
|
1477
|
-
if (p === 'P2')
|
|
1478
|
-
return 2;
|
|
1479
|
-
return 3;
|
|
1480
|
-
}
|
|
1481
1282
|
// --- Section 1: Unimplemented agents ---
|
|
1482
1283
|
if (hasImplementationData(input)) {
|
|
1483
1284
|
const sd = rec(input.implementationState.stateData);
|
|
1484
1285
|
const stateAgents = arr(sd.agents);
|
|
1485
|
-
const implementedNames = new Set(stateAgents
|
|
1486
|
-
.map((a) => rec(a))
|
|
1487
|
-
.filter(a => str(a.status) === 'implemented' || str(a.status) === 'modified')
|
|
1488
|
-
.map(a => str(a.name).toLowerCase().trim()));
|
|
1489
1286
|
const unimplemented = [];
|
|
1490
1287
|
for (const sa of stateAgents) {
|
|
1491
1288
|
const a = rec(sa);
|
|
@@ -1495,20 +1292,8 @@ function buildRecommendations(input) {
|
|
|
1495
1292
|
const name = str(a.name);
|
|
1496
1293
|
const bpAgent = team.find((t) => str(rec(t).name).toLowerCase().trim() === name.toLowerCase().trim());
|
|
1497
1294
|
const role = bpAgent ? str(rec(bpAgent).role) || str(rec(bpAgent).agentRole) : '-';
|
|
1498
|
-
|
|
1499
|
-
const phase = epic?.phase || '-';
|
|
1500
|
-
const priority = epic?.priority || '-';
|
|
1501
|
-
unimplemented.push({
|
|
1502
|
-
name,
|
|
1503
|
-
role,
|
|
1504
|
-
status,
|
|
1505
|
-
phase,
|
|
1506
|
-
priority,
|
|
1507
|
-
priorityNum: priorityKey(priority),
|
|
1508
|
-
});
|
|
1295
|
+
unimplemented.push({ name, role, status });
|
|
1509
1296
|
}
|
|
1510
|
-
// Sort by roadmap priority
|
|
1511
|
-
unimplemented.sort((a, b) => a.priorityNum - b.priorityNum);
|
|
1512
1297
|
if (unimplemented.length > 0) {
|
|
1513
1298
|
lines.push('## Next Agents to Implement', '');
|
|
1514
1299
|
for (const agent of unimplemented) {
|
|
@@ -1516,8 +1301,6 @@ function buildRecommendations(input) {
|
|
|
1516
1301
|
const statusLabel = agent.status === 'in_progress' ? ' (in progress)' : '';
|
|
1517
1302
|
lines.push(`### ${recNum}. ${agent.status === 'in_progress' ? 'Continue' : 'Implement'} ${agent.name}${statusLabel}`, '');
|
|
1518
1303
|
lines.push(`Role: ${agent.role}`);
|
|
1519
|
-
if (agent.phase !== '-')
|
|
1520
|
-
lines.push(`Roadmap phase: ${agent.phase} | Priority: ${agent.priority}`);
|
|
1521
1304
|
lines.push(`Read agent spec in \`references/agent-specifications.md\`.`, '');
|
|
1522
1305
|
}
|
|
1523
1306
|
}
|
|
@@ -1843,7 +1626,7 @@ function buildGettingStartedReturnVisit(input) {
|
|
|
1843
1626
|
lines.push('## Step 2: Follow recommendations');
|
|
1844
1627
|
lines.push('');
|
|
1845
1628
|
lines.push('Read `RECOMMENDATIONS.md` for prioritized next actions:');
|
|
1846
|
-
lines.push('- Agents to implement next
|
|
1629
|
+
lines.push('- Agents to implement next');
|
|
1847
1630
|
lines.push('- Metrics that need attention (deviations from targets)');
|
|
1848
1631
|
lines.push('- Deviations from spec that warrant review');
|
|
1849
1632
|
lines.push('');
|
|
@@ -1976,7 +1759,6 @@ function buildGettingStarted(input) {
|
|
|
1976
1759
|
lines.push('');
|
|
1977
1760
|
lines.push('- `references/agent-specifications.md` -- detailed agent team design (start here)');
|
|
1978
1761
|
lines.push('- `references/architecture-decisions.md` -- platform rationale and integration gaps');
|
|
1979
|
-
lines.push('- `references/implementation-roadmap.md` -- phased rollout plan with epics and stories');
|
|
1980
1762
|
lines.push('- `references/guardrails-and-governance.md` -- risk controls and escalation rules');
|
|
1981
1763
|
lines.push('');
|
|
1982
1764
|
// Step 2
|
|
@@ -2039,7 +1821,7 @@ function buildGettingStarted(input) {
|
|
|
2039
1821
|
// Step 3
|
|
2040
1822
|
lines.push('## Step 3: Build and validate the pilot');
|
|
2041
1823
|
lines.push('');
|
|
2042
|
-
lines.push('Check `
|
|
1824
|
+
lines.push('Check the Phase 1 section in `SKILL.md` for pilot scope.');
|
|
2043
1825
|
lines.push('Build the lead agent first. **Do not expand to remaining agents until the');
|
|
2044
1826
|
lines.push('pilot is fully working with real data.** This is a gate, not a suggestion.');
|
|
2045
1827
|
lines.push('');
|
|
@@ -2245,7 +2027,7 @@ echo "--- Optional Files ---"
|
|
|
2245
2027
|
check_optional "references/business-context.md"
|
|
2246
2028
|
check_optional "references/organization-context.md"
|
|
2247
2029
|
check_optional "references/financial-case.md"
|
|
2248
|
-
|
|
2030
|
+
|
|
2249
2031
|
check_optional "references/guardrails-and-governance.md"
|
|
2250
2032
|
check_optional "references/evaluation-criteria.md"
|
|
2251
2033
|
check_optional "references/platform-connectivity.md"
|
|
@@ -2350,6 +2132,11 @@ function buildPlatformConnectivity() {
|
|
|
2350
2132
|
// IMPLEMENTATION STATE TEMPLATE
|
|
2351
2133
|
// =============================================================================
|
|
2352
2134
|
function buildImplementationState(input) {
|
|
2135
|
+
// If synced state exists with real progress, pre-populate from it
|
|
2136
|
+
if (hasImplementationData(input)) {
|
|
2137
|
+
return buildPopulatedImplementationState(input);
|
|
2138
|
+
}
|
|
2139
|
+
// First download: generate blank template from blueprint
|
|
2353
2140
|
const bp = input.blueprintData;
|
|
2354
2141
|
const team = getTeam(bp);
|
|
2355
2142
|
const pattern = getAgenticPattern(bp);
|
|
@@ -2441,6 +2228,165 @@ function buildImplementationState(input) {
|
|
|
2441
2228
|
}
|
|
2442
2229
|
return lines.join('\n') + '\n';
|
|
2443
2230
|
}
|
|
2231
|
+
// Helper to escape a string for YAML double-quoted values
|
|
2232
|
+
function yamlEscape(value) {
|
|
2233
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
2234
|
+
}
|
|
2235
|
+
// Render a YAML string array inline, e.g. ["a", "b"] or []
|
|
2236
|
+
function yamlStringArray(items, indent) {
|
|
2237
|
+
if (items.length === 0)
|
|
2238
|
+
return '[]';
|
|
2239
|
+
// Multi-line for readability
|
|
2240
|
+
return '\n' + items.map(item => `${indent} - "${yamlEscape(item)}"`).join('\n');
|
|
2241
|
+
}
|
|
2242
|
+
function buildPopulatedImplementationState(input) {
|
|
2243
|
+
const state = input.implementationState;
|
|
2244
|
+
const sd = rec(state.stateData);
|
|
2245
|
+
const bp = input.blueprintData;
|
|
2246
|
+
const team = getTeam(bp);
|
|
2247
|
+
const pattern = getAgenticPattern(bp);
|
|
2248
|
+
const lines = [];
|
|
2249
|
+
// Header
|
|
2250
|
+
lines.push('# implementation-state.yaml');
|
|
2251
|
+
lines.push('# Pre-populated from last sync. Update and re-sync as implementation progresses.');
|
|
2252
|
+
lines.push(`# Sync back to Agent Blueprint: agentblueprint sync --blueprint ${input.blueprintId}`);
|
|
2253
|
+
lines.push('');
|
|
2254
|
+
lines.push(`schema_version: "${str(sd.schema_version) || '1.0'}"`);
|
|
2255
|
+
lines.push(`blueprint_id: "${input.blueprintId}"`);
|
|
2256
|
+
lines.push(`last_updated: "${str(sd.last_updated)}"`);
|
|
2257
|
+
lines.push('');
|
|
2258
|
+
lines.push(`overall_status: ${str(sd.overall_status) || 'not_started'} # not_started | in_progress | partial | complete`);
|
|
2259
|
+
lines.push('');
|
|
2260
|
+
// Platform
|
|
2261
|
+
const plat = rec(sd.platform);
|
|
2262
|
+
lines.push('platform:');
|
|
2263
|
+
lines.push(` name: "${yamlEscape(str(plat.name))}"`);
|
|
2264
|
+
lines.push(` version: "${yamlEscape(str(plat.version))}"`);
|
|
2265
|
+
lines.push(` environment: "${yamlEscape(str(plat.environment))}"`);
|
|
2266
|
+
lines.push('');
|
|
2267
|
+
// Build lookup of synced agents by lowercase name
|
|
2268
|
+
const stateAgents = arr(sd.agents);
|
|
2269
|
+
const stateAgentsByName = new Map();
|
|
2270
|
+
for (const sa of stateAgents) {
|
|
2271
|
+
const a = rec(sa);
|
|
2272
|
+
const name = str(a.name).toLowerCase().trim();
|
|
2273
|
+
if (name)
|
|
2274
|
+
stateAgentsByName.set(name, a);
|
|
2275
|
+
}
|
|
2276
|
+
// Build lookup of blueprint agents by lowercase name for role/tools hints
|
|
2277
|
+
const bpAgentsByName = new Map();
|
|
2278
|
+
for (const ta of team) {
|
|
2279
|
+
const a = ta;
|
|
2280
|
+
const name = str(a.name).toLowerCase().trim();
|
|
2281
|
+
if (name)
|
|
2282
|
+
bpAgentsByName.set(name, a);
|
|
2283
|
+
}
|
|
2284
|
+
// Merge: start with synced agents, then add any blueprint agents not in state
|
|
2285
|
+
const seenNames = new Set();
|
|
2286
|
+
const mergedAgents = [];
|
|
2287
|
+
for (const sa of stateAgents) {
|
|
2288
|
+
const a = rec(sa);
|
|
2289
|
+
const name = str(a.name).toLowerCase().trim();
|
|
2290
|
+
seenNames.add(name);
|
|
2291
|
+
mergedAgents.push({ stateAgent: a, bpAgent: bpAgentsByName.get(name) || null });
|
|
2292
|
+
}
|
|
2293
|
+
for (const ta of team) {
|
|
2294
|
+
const a = ta;
|
|
2295
|
+
const name = str(a.name).toLowerCase().trim();
|
|
2296
|
+
if (!seenNames.has(name)) {
|
|
2297
|
+
seenNames.add(name);
|
|
2298
|
+
mergedAgents.push({ stateAgent: null, bpAgent: a });
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
// Agents
|
|
2302
|
+
if (mergedAgents.length === 0) {
|
|
2303
|
+
lines.push('agents: []');
|
|
2304
|
+
}
|
|
2305
|
+
else {
|
|
2306
|
+
lines.push('agents:');
|
|
2307
|
+
for (let i = 0; i < mergedAgents.length; i++) {
|
|
2308
|
+
const { stateAgent, bpAgent } = mergedAgents[i];
|
|
2309
|
+
// Name from state or blueprint
|
|
2310
|
+
const name = stateAgent ? str(stateAgent.name) : str(bpAgent.name);
|
|
2311
|
+
const escapedName = yamlEscape(name);
|
|
2312
|
+
// Role/tools hint from blueprint
|
|
2313
|
+
if (bpAgent) {
|
|
2314
|
+
const type = str(bpAgent.agentRole) || str(bpAgent.orchestrationRole) || str(bpAgent.type) || 'Worker';
|
|
2315
|
+
const tools = arr(bpAgent.enhancedTools).map((t) => str(t.name)).filter(Boolean);
|
|
2316
|
+
const toolHint = tools.length > 0 ? ` | tools: ${tools.join(', ')}` : '';
|
|
2317
|
+
lines.push(` - name: "${escapedName}"`);
|
|
2318
|
+
lines.push(` # role: ${type}${toolHint}`);
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
lines.push(` - name: "${escapedName}"`);
|
|
2322
|
+
}
|
|
2323
|
+
if (stateAgent) {
|
|
2324
|
+
const status = str(stateAgent.status) || 'not_started';
|
|
2325
|
+
const artifact = str(stateAgent.platform_artifact);
|
|
2326
|
+
const deviations = arr(stateAgent.deviations).map((d) => str(d)).filter(Boolean);
|
|
2327
|
+
const integrations = arr(stateAgent.integrations_connected).map((ic) => str(ic)).filter(Boolean);
|
|
2328
|
+
const notes = str(stateAgent.notes);
|
|
2329
|
+
if (i === 0) {
|
|
2330
|
+
lines.push(` status: ${status} # not_started | in_progress | implemented | modified | skipped`);
|
|
2331
|
+
lines.push(` platform_artifact: "${yamlEscape(artifact)}"`);
|
|
2332
|
+
}
|
|
2333
|
+
else {
|
|
2334
|
+
lines.push(` status: ${status}`);
|
|
2335
|
+
lines.push(` platform_artifact: "${yamlEscape(artifact)}"`);
|
|
2336
|
+
}
|
|
2337
|
+
lines.push(` deviations: ${yamlStringArray(deviations, ' ')}`);
|
|
2338
|
+
lines.push(` integrations_connected: ${yamlStringArray(integrations, ' ')}`);
|
|
2339
|
+
lines.push(` notes: "${yamlEscape(notes)}"`);
|
|
2340
|
+
}
|
|
2341
|
+
else {
|
|
2342
|
+
// Blueprint agent not yet in synced state
|
|
2343
|
+
if (i === 0) {
|
|
2344
|
+
lines.push(' status: not_started # not_started | in_progress | implemented | modified | skipped');
|
|
2345
|
+
lines.push(' platform_artifact: ""');
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
lines.push(' status: not_started');
|
|
2349
|
+
lines.push(' platform_artifact: ""');
|
|
2350
|
+
}
|
|
2351
|
+
lines.push(' deviations: []');
|
|
2352
|
+
lines.push(' integrations_connected: []');
|
|
2353
|
+
lines.push(' notes: ""');
|
|
2354
|
+
}
|
|
2355
|
+
if (i < mergedAgents.length - 1)
|
|
2356
|
+
lines.push('');
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
lines.push('');
|
|
2360
|
+
// Architecture
|
|
2361
|
+
const arch = rec(sd.architecture);
|
|
2362
|
+
const archPattern = str(arch.pattern);
|
|
2363
|
+
const archDeviations = arr(arch.deviations).map((d) => str(d)).filter(Boolean);
|
|
2364
|
+
const archComponents = arr(arch.additional_components).map((c) => str(c)).filter(Boolean);
|
|
2365
|
+
lines.push('architecture:');
|
|
2366
|
+
lines.push(` pattern: "${yamlEscape(archPattern)}"${archPattern ? '' : ` # actual pattern used (spec recommends: ${pattern})`}`);
|
|
2367
|
+
lines.push(` deviations: ${yamlStringArray(archDeviations, ' ')}`);
|
|
2368
|
+
lines.push(` additional_components: ${yamlStringArray(archComponents, ' ')}`);
|
|
2369
|
+
lines.push('');
|
|
2370
|
+
// Metrics observed
|
|
2371
|
+
const metricsObserved = arr(sd.metrics_observed);
|
|
2372
|
+
if (metricsObserved.length > 0) {
|
|
2373
|
+
lines.push('metrics_observed:');
|
|
2374
|
+
for (const m of metricsObserved) {
|
|
2375
|
+
const mr = rec(m);
|
|
2376
|
+
lines.push(` - metric: "${yamlEscape(str(mr.metric))}"`);
|
|
2377
|
+
lines.push(` target: "${yamlEscape(str(mr.target))}"`);
|
|
2378
|
+
lines.push(` actual: "${yamlEscape(str(mr.actual))}"`);
|
|
2379
|
+
lines.push(` measured_at: "${yamlEscape(str(mr.measured_at))}"`);
|
|
2380
|
+
if (str(mr.source)) {
|
|
2381
|
+
lines.push(` source: "${yamlEscape(str(mr.source))}"`);
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
else {
|
|
2386
|
+
lines.push('metrics_observed: []');
|
|
2387
|
+
}
|
|
2388
|
+
return lines.join('\n') + '\n';
|
|
2389
|
+
}
|
|
2444
2390
|
// =============================================================================
|
|
2445
2391
|
// AGENTS.MD -- UNIVERSAL SYNC RULES
|
|
2446
2392
|
// =============================================================================
|
|
@@ -2575,7 +2521,6 @@ export function renderSkillDirectory(input) {
|
|
|
2575
2521
|
files.set('references/organization-context.md', buildOrganizationContext(input));
|
|
2576
2522
|
files.set('references/agent-specifications.md', buildAgentSpecifications(input));
|
|
2577
2523
|
files.set('references/financial-case.md', buildFinancialCase(input));
|
|
2578
|
-
files.set('references/implementation-roadmap.md', buildImplementationRoadmap(input));
|
|
2579
2524
|
files.set('references/architecture-decisions.md', buildArchitectureDecisions(input));
|
|
2580
2525
|
files.set('references/guardrails-and-governance.md', buildGuardrailsAndGovernance(input));
|
|
2581
2526
|
files.set('references/evaluation-criteria.md', buildEvaluationCriteria(input));
|