Skip to content

Commit 34ae566

Browse files
committed
fix(showcase): make resolveD5 strict on missing mapped sub-rows
A multi-key D5 family with a missing mapped sub-row is now unverified (status null), not credited green from the present rows. A present red sub-row still yields red. Mirrors isD5Green's every(...) so both consumers agree.
1 parent 268d12a commit 34ae566

2 files changed

Lines changed: 82 additions & 10 deletions

File tree

showcase/shell-dashboard/src/lib/__tests__/cell-model.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,64 @@ describe("buildCellModel", () => {
344344
// D6-ceiling: D5 green but D6 absent → amber
345345
expect(model.chipColor).toBe("amber");
346346
});
347+
348+
it("does not credit D5 green when one mapped sub-row is MISSING (strict)", () => {
349+
// beautiful-chat maps to 5 sub-keys; emit only 4 (bar-chart missing).
350+
// A missing mapped sub-row means the family is unverified, so D5 must
351+
// NOT be credited green — it returns status:null (no-data), matching
352+
// `isD5Green`'s `every(...)`. achievedDepth caps below 5; A1 renders
353+
// the unverified ladder gray.
354+
const live = mapOf([
355+
row(keyFor("e2e", "agno", "beautiful-chat"), "e2e", "green"),
356+
row(keyFor("chat", "agno"), "chat", "green"),
357+
row(keyFor("d5", "agno", "beautiful-chat-toggle-theme"), "d5", "green"),
358+
row(keyFor("d5", "agno", "beautiful-chat-pie-chart"), "d5", "green"),
359+
// beautiful-chat-bar-chart intentionally omitted.
360+
row(
361+
keyFor("d5", "agno", "beautiful-chat-search-flights"),
362+
"d5",
363+
"green",
364+
),
365+
row(
366+
keyFor("d5", "agno", "beautiful-chat-schedule-meeting"),
367+
"d5",
368+
"green",
369+
),
370+
]);
371+
const model = buildCellModel(live, wiredInput("agno", "beautiful-chat"));
372+
expect(model.d5!.exists).toBe(true);
373+
// Missing sub-row → no-data, NOT green and NOT red.
374+
expect(model.d5!.status).toBeNull();
375+
expect(model.achievedDepth).toBe(4);
376+
// Unverified ladder (D5 null), D6 absent → gray.
377+
expect(model.chipColor).toBe("gray");
378+
});
379+
380+
it("still reports red when a present sub-row is red even if another is missing", () => {
381+
// A present red sub-row signals a real failure regardless of a missing
382+
// sibling — red dominates no-data.
383+
const live = mapOf([
384+
row(keyFor("e2e", "agno", "beautiful-chat"), "e2e", "green"),
385+
row(keyFor("chat", "agno"), "chat", "green"),
386+
row(keyFor("d5", "agno", "beautiful-chat-toggle-theme"), "d5", "green"),
387+
row(keyFor("d5", "agno", "beautiful-chat-pie-chart"), "d5", "red"),
388+
// bar-chart missing; one present sub-row is red.
389+
row(
390+
keyFor("d5", "agno", "beautiful-chat-search-flights"),
391+
"d5",
392+
"green",
393+
),
394+
row(
395+
keyFor("d5", "agno", "beautiful-chat-schedule-meeting"),
396+
"d5",
397+
"green",
398+
),
399+
]);
400+
const model = buildCellModel(live, wiredInput("agno", "beautiful-chat"));
401+
expect(model.d5!.status).toBe("red");
402+
expect(model.achievedDepth).toBe(4);
403+
expect(model.chipColor).toBe("red");
404+
});
347405
});
348406

349407
// ── No live data at all → D0 gray ──────────────────────────────────

showcase/shell-dashboard/src/lib/cell-model.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,13 @@ function resolveD4(live: LiveStatusMap, slug: string, now: number): TestLevel {
169169
* independent of `CATALOG_TO_D5_KEY` order. Only green is downgraded; a stale
170170
* red/degraded sub-row already signals a problem.
171171
*
172-
* NOTE on missing sub-rows: this fold only considers sub-rows that are PRESENT
173-
* — a missing row is SKIPPED (`if (!row) continue;`), not treated as failing.
174-
* So a multi-key family with only some sub-rows emitted can still be credited
175-
* green from those present rows. This DIVERGES from `depth-utils.ts`
176-
* `isD5Green`, which uses `d5Keys.every(...)` and therefore requires every
177-
* mapped key to be present AND green-and-fresh; a missing row makes the whole
178-
* family non-green there. The per-row stale-green→degraded downgrade IS
179-
* mirrored between the two; only the partial-emission (missing-row) handling
180-
* differs.
172+
* STRICT on missing sub-rows: a multi-key family is credited green ONLY when
173+
* EVERY mapped sub-row is present and green-and-fresh — a missing mapped
174+
* sub-row forces the family out of green and resolves to `status: null`
175+
* (no-data/unverified), so `achievedDepth` caps below 5 and the chip renders
176+
* gray. A present RED sub-row still yields red (red dominates no-data). This
177+
* matches `depth-utils.ts` `isD5Green`, which uses `d5Keys.every(...)`; both
178+
* consumers now agree on partial-emission handling.
181179
*/
182180
function resolveD5(
183181
live: LiveStatusMap,
@@ -194,9 +192,16 @@ function resolveD5(
194192

195193
let worstRow: StatusRow | null = null;
196194
let worstState: State | null = null;
195+
let anyMissing = false;
197196
for (const d5Key of d5Keys) {
198197
const row = live.get(keyFor("d5", slug, d5Key)) ?? null;
199-
if (!row) continue;
198+
if (!row) {
199+
// STRICT: a missing mapped sub-row means the family is unverified —
200+
// it can no longer be credited green. Mirrors `isD5Green`'s
201+
// `every(...)` in depth-utils.ts so both consumers agree.
202+
anyMissing = true;
203+
continue;
204+
}
200205
// Per-row staleness downgrade applied BEFORE the fold: a green sub-row
201206
// that is stale folds in as `degraded` so it can never win the all-green
202207
// tie and mask a fresh-green sibling.
@@ -219,6 +224,15 @@ function resolveD5(
219224
return { exists: true, status: null, row: null };
220225
}
221226

227+
// STRICT missing-sub-row handling: when a mapped sub-row is absent the
228+
// family is unverified. A present RED sub-row still signals a real failure
229+
// (red dominates no-data), but a present green/degraded fold must NOT be
230+
// credited — collapse it to no-data (status: null) so achievedDepth caps
231+
// below 5 and the chip renders gray, not a false-green/amber.
232+
if (anyMissing && worstState !== "red") {
233+
return { exists: true, status: null, row: null };
234+
}
235+
222236
return {
223237
exists: true,
224238
status: stateToTestStatus(worstState),

0 commit comments

Comments
 (0)