@zigrivers/scaffold 3.19.0 → 3.20.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.
@@ -0,0 +1,535 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { generateMultiServiceDashboardData, generateMultiServiceHtml } from './generator.js';
3
+ import { PHASES } from '../types/frontmatter.js';
4
+ function makeState(steps, nextEligible = []) {
5
+ return {
6
+ 'schema-version': 1,
7
+ 'scaffold-version': '2.0.0',
8
+ init_methodology: 'deep',
9
+ config_methodology: 'deep',
10
+ 'init-mode': 'greenfield',
11
+ created: '2024-01-01T00:00:00.000Z',
12
+ in_progress: null,
13
+ steps,
14
+ next_eligible: nextEligible,
15
+ 'extra-steps': [],
16
+ };
17
+ }
18
+ function makeMetaPrompt(name, phase, order, overrides = {}) {
19
+ return {
20
+ stepName: name,
21
+ filePath: `/pipeline/${name}.md`,
22
+ frontmatter: {
23
+ name,
24
+ description: `Description for ${name}`,
25
+ summary: `Summary for ${name}`,
26
+ phase,
27
+ order,
28
+ dependencies: [],
29
+ outputs: [`docs/${name}.md`],
30
+ conditional: null,
31
+ knowledgeBase: [],
32
+ reads: [],
33
+ stateless: false,
34
+ category: 'pipeline',
35
+ ...overrides,
36
+ },
37
+ body: `# ${name}\n\nBody for ${name}.`,
38
+ sections: {},
39
+ };
40
+ }
41
+ function makeMetaPrompts(entries) {
42
+ const map = new Map();
43
+ for (const [name, phase, order, overrides] of entries) {
44
+ map.set(name, makeMetaPrompt(name, phase, order, overrides ?? {}));
45
+ }
46
+ return map;
47
+ }
48
+ describe('generateMultiServiceDashboardData', () => {
49
+ it('aggregates two services with different progress levels', () => {
50
+ const metaPrompts = makeMetaPrompts([
51
+ ['create-prd', 'pre', 100],
52
+ ['user-stories', 'pre', 110],
53
+ ['tech-stack', 'foundation', 200],
54
+ ['system-architecture', 'architecture', 700],
55
+ ]);
56
+ // Service A: 2 completed out of 4 → 50%
57
+ const stateA = makeState({
58
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
59
+ 'user-stories': { status: 'completed', source: 'pipeline', produces: [] },
60
+ 'tech-stack': { status: 'pending', source: 'pipeline', produces: [] },
61
+ 'system-architecture': { status: 'pending', source: 'pipeline', produces: [] },
62
+ }, ['tech-stack']);
63
+ // Service B: 1 completed + 1 skipped out of 4 → 50% too, but different
64
+ const stateB = makeState({
65
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
66
+ 'user-stories': { status: 'skipped', source: 'pipeline', produces: [] },
67
+ 'tech-stack': { status: 'in_progress', source: 'pipeline', produces: [] },
68
+ 'system-architecture': { status: 'pending', source: 'pipeline', produces: [] },
69
+ }, ['system-architecture']);
70
+ const opts = {
71
+ services: [
72
+ { name: 'svc-a', projectType: 'backend', state: stateA, metaPrompts },
73
+ { name: 'svc-b', projectType: 'web-app', state: stateB, metaPrompts },
74
+ ],
75
+ methodology: 'deep',
76
+ };
77
+ const data = generateMultiServiceDashboardData(opts);
78
+ expect(data.services).toHaveLength(2);
79
+ expect(data.aggregate.totalServices).toBe(2);
80
+ const a = data.services.find(s => s.name === 'svc-a');
81
+ const b = data.services.find(s => s.name === 'svc-b');
82
+ expect(a.completed).toBe(2);
83
+ expect(a.skipped).toBe(0);
84
+ expect(a.pending).toBe(2);
85
+ expect(a.inProgress).toBe(0);
86
+ expect(a.total).toBe(4);
87
+ expect(a.percentage).toBe(50);
88
+ expect(a.projectType).toBe('backend');
89
+ expect(b.completed).toBe(1);
90
+ expect(b.skipped).toBe(1);
91
+ expect(b.pending).toBe(1);
92
+ expect(b.inProgress).toBe(1);
93
+ expect(b.total).toBe(4);
94
+ expect(b.percentage).toBe(50);
95
+ expect(b.projectType).toBe('web-app');
96
+ expect(data.aggregate.averagePercentage).toBe(50);
97
+ expect(data.aggregate.servicesComplete).toBe(0);
98
+ });
99
+ it('handles empty services array', () => {
100
+ const data = generateMultiServiceDashboardData({
101
+ services: [],
102
+ methodology: 'deep',
103
+ });
104
+ expect(data.services).toEqual([]);
105
+ expect(data.aggregate.totalServices).toBe(0);
106
+ expect(data.aggregate.averagePercentage).toBe(0);
107
+ expect(data.aggregate.servicesComplete).toBe(0);
108
+ expect(data.aggregate.servicesByPhase).toHaveLength(PHASES.length);
109
+ for (const phase of data.aggregate.servicesByPhase) {
110
+ expect(phase.reachedCount).toBe(0);
111
+ }
112
+ });
113
+ it('single service at 100% → averagePercentage 100, servicesComplete 1', () => {
114
+ const metaPrompts = makeMetaPrompts([
115
+ ['create-prd', 'pre', 100],
116
+ ['user-stories', 'pre', 110],
117
+ ]);
118
+ const state = makeState({
119
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
120
+ 'user-stories': { status: 'skipped', source: 'pipeline', produces: [] },
121
+ }, []);
122
+ const data = generateMultiServiceDashboardData({
123
+ services: [
124
+ { name: 'svc-done', projectType: 'library', state, metaPrompts },
125
+ ],
126
+ methodology: 'deep',
127
+ });
128
+ expect(data.aggregate.averagePercentage).toBe(100);
129
+ expect(data.aggregate.servicesComplete).toBe(1);
130
+ expect(data.services[0].percentage).toBe(100);
131
+ expect(data.services[0].currentPhaseNumber).toBeNull();
132
+ expect(data.services[0].currentPhaseName).toBeNull();
133
+ });
134
+ it('currentPhaseNumber is lowest phase with pending/in_progress', () => {
135
+ const metaPrompts = makeMetaPrompts([
136
+ ['create-prd', 'pre', 100],
137
+ ['tech-stack', 'foundation', 200],
138
+ ['system-architecture', 'architecture', 700],
139
+ ]);
140
+ // create-prd completed (pre), tech-stack pending (foundation),
141
+ // system-architecture in_progress (architecture)
142
+ // Lowest phase with pending/in_progress = foundation (number 2)
143
+ const state = makeState({
144
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
145
+ 'tech-stack': { status: 'pending', source: 'pipeline', produces: [] },
146
+ 'system-architecture': { status: 'in_progress', source: 'pipeline', produces: [] },
147
+ }, ['tech-stack']);
148
+ const data = generateMultiServiceDashboardData({
149
+ services: [
150
+ { name: 'svc', projectType: 'backend', state, metaPrompts },
151
+ ],
152
+ methodology: 'deep',
153
+ });
154
+ expect(data.services[0].currentPhaseNumber).toBe(2);
155
+ expect(data.services[0].currentPhaseName).toBe('Project Foundation');
156
+ });
157
+ it('currentPhaseNumber null when all steps completed/skipped', () => {
158
+ const metaPrompts = makeMetaPrompts([
159
+ ['create-prd', 'pre', 100],
160
+ ['tech-stack', 'foundation', 200],
161
+ ]);
162
+ const state = makeState({
163
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
164
+ 'tech-stack': { status: 'skipped', source: 'pipeline', produces: [] },
165
+ }, []);
166
+ const data = generateMultiServiceDashboardData({
167
+ services: [
168
+ { name: 'svc-done', projectType: 'backend', state, metaPrompts },
169
+ ],
170
+ methodology: 'deep',
171
+ });
172
+ expect(data.services[0].currentPhaseNumber).toBeNull();
173
+ expect(data.services[0].currentPhaseName).toBeNull();
174
+ });
175
+ it('nextEligibleSlug reads from state.next_eligible[0]; null when empty', () => {
176
+ const metaPrompts = makeMetaPrompts([
177
+ ['create-prd', 'pre', 100],
178
+ ['user-stories', 'pre', 110, { summary: 'Write user stories' }],
179
+ ]);
180
+ const stateWithNext = makeState({
181
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
182
+ 'user-stories': { status: 'pending', source: 'pipeline', produces: [] },
183
+ }, ['user-stories']);
184
+ const stateEmptyNext = makeState({
185
+ 'create-prd': { status: 'pending', source: 'pipeline', produces: [] },
186
+ }, []);
187
+ const data = generateMultiServiceDashboardData({
188
+ services: [
189
+ { name: 'svc-a', projectType: 'backend', state: stateWithNext, metaPrompts },
190
+ { name: 'svc-b', projectType: 'backend', state: stateEmptyNext, metaPrompts },
191
+ ],
192
+ methodology: 'deep',
193
+ });
194
+ const a = data.services.find(s => s.name === 'svc-a');
195
+ const b = data.services.find(s => s.name === 'svc-b');
196
+ expect(a.nextEligibleSlug).toBe('user-stories');
197
+ expect(a.nextEligibleSummary).toBe('Write user stories');
198
+ expect(b.nextEligibleSlug).toBeNull();
199
+ expect(b.nextEligibleSummary).toBeNull();
200
+ });
201
+ it('servicesByPhase counts services with ≥1 completed/skipped step per phase', () => {
202
+ const metaPrompts = makeMetaPrompts([
203
+ ['create-prd', 'pre', 100],
204
+ ['tech-stack', 'foundation', 200],
205
+ ['system-architecture', 'architecture', 700],
206
+ ]);
207
+ // Service A reached pre (completed) but not foundation
208
+ const stateA = makeState({
209
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
210
+ 'tech-stack': { status: 'pending', source: 'pipeline', produces: [] },
211
+ });
212
+ // Service B reached pre (skipped) and foundation (completed)
213
+ const stateB = makeState({
214
+ 'create-prd': { status: 'skipped', source: 'pipeline', produces: [] },
215
+ 'tech-stack': { status: 'completed', source: 'pipeline', produces: [] },
216
+ });
217
+ // Service C reached pre, foundation, and architecture
218
+ const stateC = makeState({
219
+ 'create-prd': { status: 'completed', source: 'pipeline', produces: [] },
220
+ 'tech-stack': { status: 'completed', source: 'pipeline', produces: [] },
221
+ 'system-architecture': { status: 'completed', source: 'pipeline', produces: [] },
222
+ });
223
+ const data = generateMultiServiceDashboardData({
224
+ services: [
225
+ { name: 'a', projectType: 'backend', state: stateA, metaPrompts },
226
+ { name: 'b', projectType: 'backend', state: stateB, metaPrompts },
227
+ { name: 'c', projectType: 'backend', state: stateC, metaPrompts },
228
+ ],
229
+ methodology: 'deep',
230
+ });
231
+ const pre = data.aggregate.servicesByPhase.find(p => p.phaseSlug === 'pre');
232
+ const foundation = data.aggregate.servicesByPhase.find(p => p.phaseSlug === 'foundation');
233
+ const architecture = data.aggregate.servicesByPhase.find(p => p.phaseSlug === 'architecture');
234
+ const vision = data.aggregate.servicesByPhase.find(p => p.phaseSlug === 'vision');
235
+ expect(pre.reachedCount).toBe(3);
236
+ expect(foundation.reachedCount).toBe(2);
237
+ expect(architecture.reachedCount).toBe(1);
238
+ expect(vision.reachedCount).toBe(0);
239
+ // metadata
240
+ expect(pre.phaseName).toBe('Product Definition');
241
+ expect(pre.phaseNumber).toBe(1);
242
+ });
243
+ it('preserves service order from input', () => {
244
+ const metaPrompts = makeMetaPrompts([
245
+ ['create-prd', 'pre', 100],
246
+ ]);
247
+ const mkSt = () => makeState({
248
+ 'create-prd': { status: 'pending', source: 'pipeline', produces: [] },
249
+ });
250
+ const data = generateMultiServiceDashboardData({
251
+ services: [
252
+ { name: 'zeta', projectType: 'backend', state: mkSt(), metaPrompts },
253
+ { name: 'alpha', projectType: 'backend', state: mkSt(), metaPrompts },
254
+ { name: 'middle', projectType: 'backend', state: mkSt(), metaPrompts },
255
+ ],
256
+ methodology: 'deep',
257
+ });
258
+ expect(data.services.map(s => s.name)).toEqual(['zeta', 'alpha', 'middle']);
259
+ });
260
+ it('includes methodology and scaffoldVersion in output', () => {
261
+ const data = generateMultiServiceDashboardData({
262
+ services: [],
263
+ methodology: 'mvp',
264
+ });
265
+ expect(data.methodology).toBe('mvp');
266
+ expect(typeof data.scaffoldVersion).toBe('string');
267
+ expect(data.scaffoldVersion.length).toBeGreaterThan(0);
268
+ expect(typeof data.generatedAt).toBe('string');
269
+ });
270
+ });
271
+ // ---------- HTML rendering ----------
272
+ function makeMultiData(overrides = {}) {
273
+ const base = {
274
+ generatedAt: new Date().toISOString(),
275
+ methodology: 'deep',
276
+ scaffoldVersion: '3.20.0',
277
+ services: [
278
+ {
279
+ name: 'api-service',
280
+ projectType: 'backend',
281
+ percentage: 42,
282
+ completed: 3,
283
+ skipped: 1,
284
+ pending: 5,
285
+ inProgress: 1,
286
+ total: 10,
287
+ currentPhaseNumber: 3,
288
+ currentPhaseName: 'System Architecture',
289
+ nextEligibleSlug: 'create-prd',
290
+ nextEligibleSummary: 'Define the product',
291
+ },
292
+ {
293
+ name: 'web-client',
294
+ projectType: 'web-app',
295
+ percentage: 100,
296
+ completed: 8,
297
+ skipped: 2,
298
+ pending: 0,
299
+ inProgress: 0,
300
+ total: 10,
301
+ currentPhaseNumber: null,
302
+ currentPhaseName: null,
303
+ nextEligibleSlug: null,
304
+ nextEligibleSummary: null,
305
+ },
306
+ ],
307
+ aggregate: {
308
+ totalServices: 2,
309
+ averagePercentage: 71,
310
+ servicesComplete: 1,
311
+ servicesByPhase: [
312
+ { phaseSlug: 'pre', phaseName: 'Product Definition', phaseNumber: 1, reachedCount: 2 },
313
+ { phaseSlug: 'foundation', phaseName: 'Project Foundation', phaseNumber: 2, reachedCount: 1 },
314
+ ],
315
+ },
316
+ };
317
+ return { ...base, ...overrides };
318
+ }
319
+ describe('generateMultiServiceHtml', () => {
320
+ it('renders service names', () => {
321
+ const html = generateMultiServiceHtml(makeMultiData());
322
+ expect(html).toContain('api-service');
323
+ expect(html).toContain('web-client');
324
+ });
325
+ it('renders project types', () => {
326
+ const html = generateMultiServiceHtml(makeMultiData());
327
+ expect(html).toContain('backend');
328
+ expect(html).toContain('web-app');
329
+ });
330
+ it('renders progress percentages', () => {
331
+ const html = generateMultiServiceHtml(makeMultiData());
332
+ expect(html).toContain('42%');
333
+ expect(html).toContain('100%');
334
+ // aggregate
335
+ expect(html).toContain('71%');
336
+ });
337
+ it('renders current phase or Complete badge', () => {
338
+ const html = generateMultiServiceHtml(makeMultiData());
339
+ // api-service has phase 3 → System Architecture
340
+ expect(html).toContain('Phase 3');
341
+ expect(html).toContain('System Architecture');
342
+ // web-client is complete
343
+ expect(html).toContain('Complete');
344
+ });
345
+ it('renders next eligible slug when present', () => {
346
+ const html = generateMultiServiceHtml(makeMultiData());
347
+ expect(html).toContain('create-prd');
348
+ expect(html).toContain('Next');
349
+ });
350
+ it('escapes HTML in service names (XSS guard)', () => {
351
+ const data = makeMultiData({
352
+ services: [
353
+ {
354
+ name: '<script>alert(1)</script>',
355
+ projectType: '<img src=x>',
356
+ percentage: 0,
357
+ completed: 0,
358
+ skipped: 0,
359
+ pending: 1,
360
+ inProgress: 0,
361
+ total: 1,
362
+ currentPhaseNumber: 1,
363
+ currentPhaseName: 'Product Definition',
364
+ nextEligibleSlug: '<b>evil</b>',
365
+ nextEligibleSummary: null,
366
+ },
367
+ ],
368
+ });
369
+ const html = generateMultiServiceHtml(data);
370
+ expect(html).not.toContain('<script>alert(1)</script>');
371
+ expect(html).toContain('&lt;script&gt;alert(1)&lt;/script&gt;');
372
+ expect(html).toContain('&lt;img src=x&gt;');
373
+ expect(html).toContain('&lt;b&gt;evil&lt;/b&gt;');
374
+ });
375
+ it('embeds data JSON in a script tag', () => {
376
+ const data = makeMultiData();
377
+ const html = generateMultiServiceHtml(data);
378
+ expect(html).toContain('<script id="scaffold-data" type="application/json">');
379
+ // JSON payload is embedded — service names should appear within the JSON block
380
+ expect(html).toContain('"api-service"');
381
+ expect(html).toContain('"web-client"');
382
+ });
383
+ it('renders services-by-phase aggregate row', () => {
384
+ const html = generateMultiServiceHtml(makeMultiData());
385
+ expect(html).toContain('Product Definition');
386
+ expect(html).toContain('Project Foundation');
387
+ });
388
+ it('renders "Not started" badge for skeleton service with total=0 (MMR P1 lock)', () => {
389
+ // Regression guard: previously currentPhaseNumber === null was treated as
390
+ // "Complete" — but missing-state skeletons also have null phase. Must be
391
+ // distinguished by total > 0.
392
+ const data = {
393
+ generatedAt: '2026-04-20T00:00:00.000Z',
394
+ methodology: 'deep',
395
+ scaffoldVersion: '3.20.0',
396
+ services: [{
397
+ name: 'skeleton', projectType: 'backend',
398
+ percentage: 0, completed: 0, skipped: 0, pending: 0, inProgress: 0, total: 0,
399
+ currentPhaseNumber: null, currentPhaseName: null,
400
+ nextEligibleSlug: null, nextEligibleSummary: null,
401
+ }],
402
+ aggregate: {
403
+ totalServices: 1, averagePercentage: 0, servicesComplete: 0,
404
+ servicesByPhase: [],
405
+ },
406
+ };
407
+ const html = generateMultiServiceHtml(data);
408
+ expect(html).toContain('Not started');
409
+ // The "Complete" label MUST NOT be rendered (CSS class definition for the
410
+ // badge can exist in the stylesheet — but the span with that class should not).
411
+ expect(html).not.toMatch(/<span class="service-complete-badge">/);
412
+ });
413
+ it('uses data-copy attribute instead of inline onclick (XSS hardening, Codex MMR P1)', () => {
414
+ const data = {
415
+ generatedAt: '2026-04-20T00:00:00.000Z',
416
+ methodology: 'deep',
417
+ scaffoldVersion: '3.20.0',
418
+ services: [{
419
+ name: 'evil\\\');alert(1)//', projectType: 'backend',
420
+ percentage: 50, completed: 1, skipped: 0, pending: 1, inProgress: 0, total: 2,
421
+ currentPhaseNumber: 1, currentPhaseName: 'Product Definition',
422
+ nextEligibleSlug: null, nextEligibleSummary: null,
423
+ }],
424
+ aggregate: {
425
+ totalServices: 1, averagePercentage: 50, servicesComplete: 0,
426
+ servicesByPhase: [],
427
+ },
428
+ };
429
+ const html = generateMultiServiceHtml(data);
430
+ // No inline onclick on the service card (attribute-based click handler only).
431
+ expect(html).not.toMatch(/<div class="service-card"[^>]*onclick=/);
432
+ // data-copy attribute carries the command — HTML-escaped but not
433
+ // JS-string-escaped, so the backslash/quote attacker payload cannot
434
+ // escape any JS context.
435
+ expect(html).toContain('data-copy="scaffold dashboard --service');
436
+ });
437
+ });
438
+ describe('generateMultiServiceDashboardData — averagePercentage rounding', () => {
439
+ it('computes averagePercentage from raw ratios, not double-rounded per-service percentages (Codex MMR P3)', () => {
440
+ // Service A: 1/40 = 2.5% (rounds to 3). Service B: 0/1 = 0% (rounds to 0).
441
+ // Raw mean of ratios: (0.025 + 0) / 2 = 0.0125 → 1% after one round.
442
+ // Double-rounded would give (3 + 0) / 2 = 1.5 → 2%. Lock the correct value.
443
+ const stepsA = {};
444
+ for (let i = 0; i < 40; i++) {
445
+ stepsA[`a${i}`] = i === 0
446
+ ? { status: 'completed', source: 'pipeline', produces: [] }
447
+ : { status: 'pending', source: 'pipeline', produces: [] };
448
+ }
449
+ const data = generateMultiServiceDashboardData({
450
+ methodology: 'deep',
451
+ services: [
452
+ {
453
+ name: 'svc-a', projectType: 'backend',
454
+ state: {
455
+ 'schema-version': 3, 'scaffold-version': '1.0.0',
456
+ init_methodology: 'deep', config_methodology: 'deep',
457
+ 'init-mode': 'greenfield', created: '2026-04-20T00:00:00.000Z',
458
+ in_progress: null, steps: stepsA,
459
+ next_eligible: [], 'extra-steps': [],
460
+ },
461
+ },
462
+ {
463
+ name: 'svc-b', projectType: 'backend',
464
+ state: {
465
+ 'schema-version': 3, 'scaffold-version': '1.0.0',
466
+ init_methodology: 'deep', config_methodology: 'deep',
467
+ 'init-mode': 'greenfield', created: '2026-04-20T00:00:00.000Z',
468
+ in_progress: null,
469
+ steps: { 'b0': { status: 'pending', source: 'pipeline', produces: [] } },
470
+ next_eligible: [], 'extra-steps': [],
471
+ },
472
+ },
473
+ ],
474
+ });
475
+ expect(data.aggregate.averagePercentage).toBe(1);
476
+ });
477
+ it('nextEligibleSummary does NOT fall back to description (MMR P2 lock)', () => {
478
+ // Regression guard: earlier code used `fm?.summary ?? fm?.description ?? null`.
479
+ // Single-service behavior is summary-only; multi-service must match so the
480
+ // card line doesn't get flooded with long descriptions.
481
+ const stepSteps = {
482
+ 'desc-only-step': { status: 'pending', source: 'pipeline', produces: [] },
483
+ };
484
+ // Meta prompt with description but NO summary
485
+ const mp = new Map([
486
+ ['desc-only-step', {
487
+ stepName: 'desc-only-step',
488
+ filePath: '/fake.md',
489
+ frontmatter: {
490
+ name: 'desc-only-step', description: 'A long description that should NOT leak',
491
+ summary: null,
492
+ phase: 'architecture', order: 1,
493
+ dependencies: [], outputs: [], conditional: null,
494
+ knowledgeBase: [], reads: [], crossReads: [],
495
+ stateless: false, category: 'pipeline',
496
+ },
497
+ body: '', sections: {},
498
+ }],
499
+ ]);
500
+ const data = generateMultiServiceDashboardData({
501
+ methodology: 'deep',
502
+ services: [{
503
+ name: 's', projectType: 'backend', metaPrompts: mp,
504
+ state: {
505
+ 'schema-version': 3, 'scaffold-version': '1.0.0',
506
+ init_methodology: 'deep', config_methodology: 'deep',
507
+ 'init-mode': 'greenfield', created: '2026-04-20T00:00:00.000Z',
508
+ in_progress: null, steps: stepSteps,
509
+ next_eligible: ['desc-only-step'], 'extra-steps': [],
510
+ },
511
+ }],
512
+ });
513
+ expect(data.services[0].nextEligibleSlug).toBe('desc-only-step');
514
+ expect(data.services[0].nextEligibleSummary).toBeNull();
515
+ });
516
+ it('skeleton service (total=0) is not counted as complete in servicesComplete', () => {
517
+ const data = generateMultiServiceDashboardData({
518
+ methodology: 'deep',
519
+ services: [{
520
+ name: 'skel', projectType: 'backend',
521
+ state: {
522
+ 'schema-version': 3, 'scaffold-version': '1.0.0',
523
+ init_methodology: 'deep', config_methodology: 'deep',
524
+ 'init-mode': 'greenfield', created: '2026-04-20T00:00:00.000Z',
525
+ in_progress: null, steps: {},
526
+ next_eligible: [], 'extra-steps': [],
527
+ },
528
+ }],
529
+ });
530
+ expect(data.aggregate.servicesComplete).toBe(0);
531
+ expect(data.services[0].total).toBe(0);
532
+ expect(data.services[0].percentage).toBe(0);
533
+ });
534
+ });
535
+ //# sourceMappingURL=multi-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-service.test.js","sourceRoot":"","sources":["../../src/dashboard/multi-service.test.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import type { DashboardData } from './generator.js';
1
+ import type { DashboardData, MultiServiceDashboardData } from './generator.js';
2
2
  export declare function escapeHtml(s: string): string;
3
3
  export declare function buildTemplate(dataJson: string, data: DashboardData): string;
4
+ export declare function buildMultiServiceTemplate(dataJson: string, data: MultiServiceDashboardData): string;
4
5
  //# sourceMappingURL=template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/dashboard/template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAGD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAwzB3E"}
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/dashboard/template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AAE9E,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAGD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAwzB3E;AAID,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,yBAAyB,GAC9B,MAAM,CAsZR"}