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.
@@ -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 — prefer implementation plan epics when available
193
- const ipEpics = input.implementationPlanData ? arr(rec(input.implementationPlanData).epics) : [];
194
- if (ipEpics.length > 0) {
195
- const pilotEpics = ipEpics.filter((e) => str(rec(e).phase).toLowerCase().includes('pilot'));
196
- const fullEpics = ipEpics.filter((e) => !str(rec(e).phase).toLowerCase().includes('pilot'));
197
- lines.push('## Phase 1: Pilot', '');
198
- if (pilotEpics.length > 0) {
199
- const seen = new Set();
200
- for (const epic of pilotEpics) {
201
- const e = rec(epic);
202
- const name = str(e.name);
203
- if (name && !seen.has(name)) {
204
- seen.add(name);
205
- lines.push(`- **${name}**${str(e.estimatedDuration) ? ` (${str(e.estimatedDuration)})` : ''}`);
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
- else {
211
- lines.push('_No pilot epics defined. See `references/implementation-roadmap.md` for phasing._', '');
212
- }
213
- lines.push('## Phase 2: Full Implementation', '');
214
- if (fullEpics.length > 0) {
215
- const seen = new Set();
216
- for (const epic of fullEpics) {
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
- else {
227
- lines.push('_See `references/implementation-roadmap.md` for full rollout plan._', '');
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('## Phase 1: Pilot', '');
232
- const phases = arr(bp.phases);
233
- const pilotPhase = phases.find((p) => str(p?.name).toLowerCase().includes('pilot') || str(p?.name).toLowerCase().includes('phase 1'));
234
- if (pilotPhase) {
235
- const p = rec(pilotPhase);
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(`**Goal:** ${str(p.phaseGoal)}`, '');
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 target:** ${str(p.phaseCost)}`);
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
- const epic = findEpicForAgent(name);
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 (ordered by roadmap priority)');
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 `references/implementation-roadmap.md` for Phase 1 scope.');
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
- check_optional "references/implementation-roadmap.md"
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));