Skip to content

Commit 1541cbc

Browse files
committed
fix(showcase/dashboard): unsupported cells show indicator instead of numeric depth
deriveDepth() was computing D2 for not_supported_features because D1/D2 are integration-scoped. Add unsupported boolean to DepthResult, guard in deriveDepth, update consumer components. 24/24 depth-utils tests pass.
1 parent 6159c18 commit 1541cbc

6 files changed

Lines changed: 90 additions & 23 deletions

File tree

showcase/shell-dashboard/src/components/__tests__/composed-cell.test.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ vi.mock("@/components/depth-utils", async () => {
6666
>("@/components/depth-utils");
6767
return {
6868
...actual,
69-
deriveDepth: vi.fn(() => ({ achieved: 2, isRegression: false })),
69+
deriveDepth: vi.fn(() => ({
70+
achieved: 2,
71+
isRegression: false,
72+
unsupported: false,
73+
})),
7074
};
7175
});
7276

showcase/shell-dashboard/src/components/__tests__/depth-utils.test.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,14 @@ describe("deriveDepth", () => {
5959
const result = deriveDepth(c, live);
6060
expect(result.achieved).toBe(0);
6161
expect(result.isRegression).toBe(false);
62+
expect(result.unsupported).toBe(false);
6263
});
6364

64-
it("returns D0 with no regression for unsupported cells regardless of live data", () => {
65-
// Unsupported cells have no probes — even if probes for the same
66-
// integration are green, the cell stays at D0 with no regression.
65+
it("returns unsupported=true for unsupported cells regardless of live data", () => {
66+
// Unsupported cells are architectural exclusions — they never enter
67+
// the depth ladder. Even if integration-scoped probes (D1/D2) are
68+
// green, the result must flag unsupported so consumers render the
69+
// no-entry indicator instead of a numeric depth like D2.
6770
const c = cell("lgp", "voice", "unsupported");
6871
const live = mapOf([
6972
row("health:lgp", "health", "green"),
@@ -73,6 +76,17 @@ describe("deriveDepth", () => {
7376
const result = deriveDepth(c, live);
7477
expect(result.achieved).toBe(0);
7578
expect(result.isRegression).toBe(false);
79+
expect(result.unsupported).toBe(true);
80+
});
81+
82+
it("returns unsupported=false for wired cells", () => {
83+
const c = cell("lgp", "agentic-chat");
84+
const live = mapOf([
85+
row("health:lgp", "health", "green"),
86+
row("agent:lgp", "agent", "green"),
87+
]);
88+
const result = deriveDepth(c, live);
89+
expect(result.unsupported).toBe(false);
7690
});
7791

7892
it("returns D0 for wired cell with no live data", () => {

showcase/shell-dashboard/src/components/cell-matrix.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,12 @@ function CategorySection({
143143
</td>
144144
{visibleIntegrations.map((int) => {
145145
const cell = cellIndex.get(`${int.slug}/${feature.id}`);
146-
const cellStatus = cell?.status ?? "unshipped";
147146
const depth: DepthResult = cell
148147
? deriveDepth(cell, liveStatus)
149-
: { achieved: 0, isRegression: false };
148+
: { achieved: 0, isRegression: false, unsupported: false };
149+
const cellStatus = depth.unsupported
150+
? "unsupported"
151+
: (cell?.status ?? "unshipped");
150152

151153
const isSelected =
152154
selectedCell?.slug === int.slug &&

showcase/shell-dashboard/src/components/depth-utils.ts

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ export interface DepthResult {
4141
achieved: AchievedDepth;
4242
/** Whether achieved depth is below the historical high-water mark (max_depth). */
4343
isRegression: boolean;
44+
/**
45+
* True when the cell's catalog status is "unsupported". Unsupported cells
46+
* never advance on the depth ladder — their `achieved` is always 0 and
47+
* `isRegression` is always false. Consumers should render the unsupported
48+
* indicator (e.g. the no-entry chip) instead of a numeric depth.
49+
*/
50+
unsupported: boolean;
4451
}
4552

4653
function isGreen(live: LiveStatusMap, key: string): boolean {
@@ -74,49 +81,79 @@ export function deriveDepth(
7481
cell: CatalogCell,
7582
live: LiveStatusMap,
7683
): DepthResult {
77-
// Unshipped and unsupported cells never advance past D0 — neither has any
78-
// probes attached, so there is no possibility of regression. (Unsupported
79-
// is a hard architectural floor; unshipped is "just unbuilt".)
80-
if (cell.status === "unshipped" || cell.status === "unsupported") {
81-
return { achieved: 0, isRegression: false };
84+
// Unsupported cells never enter the depth ladder at all — they're
85+
// architectural exclusions, not "cells at D0". Flag them explicitly
86+
// so consumers render the unsupported indicator instead of D0.
87+
if (cell.status === "unsupported") {
88+
return { achieved: 0, isRegression: false, unsupported: true };
89+
}
90+
91+
// Unshipped cells never advance past D0 — no probes attached, no
92+
// possibility of regression.
93+
if (cell.status === "unshipped") {
94+
return { achieved: 0, isRegression: false, unsupported: false };
8295
}
8396

8497
// D0: cell exists (wired or stub) — always true if we reach here.
8598
let achieved: AchievedDepth = 0;
8699

87100
// D1: health:<slug> green
88101
if (!isGreen(live, keyFor("health", cell.integration))) {
89-
return { achieved, isRegression: achieved < cell.max_depth };
102+
return {
103+
achieved,
104+
isRegression: achieved < cell.max_depth,
105+
unsupported: false,
106+
};
90107
}
91108
achieved = 1;
92109

93110
// D2: agent:<slug> green
94111
if (!isGreen(live, keyFor("agent", cell.integration))) {
95-
return { achieved, isRegression: achieved < cell.max_depth };
112+
return {
113+
achieved,
114+
isRegression: achieved < cell.max_depth,
115+
unsupported: false,
116+
};
96117
}
97118
achieved = 2;
98119

99120
// D3: e2e:<slug>/<featureId> green (per-cell)
100121
// Guard: skip D3+ if feature is null (no per-cell e2e to evaluate).
101122
if (cell.feature === null) {
102-
return { achieved, isRegression: achieved < cell.max_depth };
123+
return {
124+
achieved,
125+
isRegression: achieved < cell.max_depth,
126+
unsupported: false,
127+
};
103128
}
104129
if (!isGreen(live, keyFor("e2e", cell.integration, cell.feature))) {
105-
return { achieved, isRegression: achieved < cell.max_depth };
130+
return {
131+
achieved,
132+
isRegression: achieved < cell.max_depth,
133+
unsupported: false,
134+
};
106135
}
107136
achieved = 3;
108137

109138
// D4: chat:<slug> OR tools:<slug> green (integration-scoped)
110139
const chatGreen = isGreen(live, keyFor("chat", cell.integration));
111140
const toolsGreen = isGreen(live, keyFor("tools", cell.integration));
112141
if (!(chatGreen || toolsGreen)) {
113-
return { achieved, isRegression: achieved < cell.max_depth };
142+
return {
143+
achieved,
144+
isRegression: achieved < cell.max_depth,
145+
unsupported: false,
146+
};
114147
}
115148
achieved = 4;
116149

117150
// D5: d5:<slug>/<d5FeatureType> green (per-cell, mapped via CATALOG_TO_D5_KEY)
118151
if (!isD5Green(live, cell.integration, cell.feature)) {
119-
return { achieved, isRegression: achieved < cell.max_depth };
152+
return {
153+
achieved,
154+
isRegression: achieved < cell.max_depth,
155+
unsupported: false,
156+
};
120157
}
121158
achieved = 5;
122159

@@ -125,5 +162,9 @@ export function deriveDepth(
125162
achieved = 6;
126163
}
127164

128-
return { achieved, isRegression: achieved < cell.max_depth };
165+
return {
166+
achieved,
167+
isRegression: achieved < cell.max_depth,
168+
unsupported: false,
169+
};
129170
}

showcase/shell-dashboard/src/components/feature-grid.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,9 @@ function CategorySection({
300300
(refCell && refDepth ? (
301301
<RefDepthCell
302302
depth={refDepth.achieved}
303-
status={refCell.status}
303+
status={
304+
refDepth.unsupported ? "unsupported" : refCell.status
305+
}
304306
regression={refDepth.isRegression}
305307
/>
306308
) : (

showcase/shell-dashboard/src/components/parity-matrix.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ function ParityCategorySection({
113113
{isOpen &&
114114
cat.features.map((feature) => {
115115
const refCell = cellIndex.get(`${referenceSlug}/${feature.id}`);
116-
const refStatus = refCell?.status ?? "unshipped";
117116
const refDepth: DepthResult = refCell
118117
? deriveDepth(refCell, liveStatus)
119-
: { achieved: 0, isRegression: false };
118+
: { achieved: 0, isRegression: false, unsupported: false };
119+
const refStatus = refDepth.unsupported
120+
? "unsupported"
121+
: (refCell?.status ?? "unshipped");
120122

121123
return (
122124
<tr
@@ -137,10 +139,12 @@ function ParityCategorySection({
137139
</td>
138140
{nonRefIntegrations.map((int) => {
139141
const cell = cellIndex.get(`${int.slug}/${feature.id}`);
140-
const cellStatus = cell?.status ?? "unshipped";
141142
const depth: DepthResult = cell
142143
? deriveDepth(cell, liveStatus)
143-
: { achieved: 0, isRegression: false };
144+
: { achieved: 0, isRegression: false, unsupported: false };
145+
const cellStatus = depth.unsupported
146+
? "unsupported"
147+
: (cell?.status ?? "unshipped");
144148

145149
return (
146150
<td

0 commit comments

Comments
 (0)