Skip to content

Commit 51e9a8f

Browse files
yyodsclaude
andcommitted
[green] derive home and support availability from the release
The home availability grid now derives every target from the selected release's profile set: a Raspberry Pi Pico 2 W definition joins the catalog (RP2350 + CYW43439 · UF2 / BOOTSEL), the deferred C3/Pico rows are planned only while a release excludes them, all five v0.6.0 targets carry deployment-consistent statuses (protected candidate · HIL pending vs qualified public release), and the lean-generic S3 rename follows Waveshare profile presence. The hero replaces the stale 'ESP32-C3 and Raspberry Pi Pico 2 W ... remain unavailable' sentence on five-profile releases with the staged-pending-validation sentence in candidate mode and a five-profile qualified lede; the home board photo is presence-gated like the flash spotlight. The support page adds the candidate branch mirroring the staged-candidate copy instead of the contradictory installer-unavailable claim, and derives the ESP32-C3 availability note from the release profile set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016KVSKkd7KUMHqKXDhPXTj5 Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent d788832 commit 51e9a8f

3 files changed

Lines changed: 84 additions & 27 deletions

File tree

‎tools/web/src/app/page.tsx‎

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
ShieldIcon,
2020
} from "@/components/icons";
2121
import { WaveshareBoardPhoto } from "@/components/waveshare-board-photo";
22-
import { releaseIncludesWaveshareLcd147b } from "@/lib/firmware-release";
22+
import {
23+
firmwareVersionUsesFiveProfiles,
24+
releaseIncludesWaveshareLcd147b,
25+
} from "@/lib/firmware-release";
2326
import {
2427
firmwareReleaseSelectedAtBuild,
2528
localFirmwarePreviewSelectedAtBuild,
@@ -82,6 +85,14 @@ export default function HomePage() {
8285
const publicBeta = firmwareRelease?.deployment === "public-beta";
8386
const waveshareLcd147b = releaseIncludesWaveshareLcd147b(firmwareRelease);
8487
const qualifiedPublic = firmwareRelease !== null && waveshareLcd147b;
88+
const fiveProfileRelease =
89+
firmwareRelease !== null &&
90+
firmwareVersionUsesFiveProfiles(firmwareRelease.version);
91+
const releaseHasWaveshareProfile = Boolean(
92+
firmwareRelease?.profiles.some(
93+
({ id }) => id === "waveshare-esp32-s3-lcd-147b",
94+
),
95+
);
8596
const firmwareTargetGroupLabel = preview
8697
? `Five exact v${preview.version} engineering targets`
8798
: qualifiedPublic
@@ -138,6 +149,13 @@ export default function HomePage() {
138149
interrupted-flash recovery passed on both exact profiles;
139150
complete release qualification continues.
140151
</>
152+
) : qualifiedPublic && fiveProfileRelease ? (
153+
<>
154+
Qualified public v{firmwareRelease.version} firmware is
155+
available for all five exact release profiles across classic
156+
ESP32, ESP32-S3, the separate Waveshare exact-board image,
157+
ESP32-C3, and the Raspberry Pi Pico 2 W.
158+
</>
141159
) : qualifiedPublic ? (
142160
<>
143161
Qualified public v{firmwareRelease.version} firmware is
@@ -156,12 +174,20 @@ export default function HomePage() {
156174
status before provisioning a board.
157175
</>
158176
)}{" "}
159-
{!preview ? (
177+
{!preview && !fiveProfileRelease ? (
160178
<>
161179
ESP32-C3 and Raspberry Pi Pico 2 W are under engineering
162180
validation and remain unavailable in the public installer.
163181
</>
164182
) : null}
183+
{!preview &&
184+
fiveProfileRelease &&
185+
firmwareRelease.deployment === "candidate" ? (
186+
<>
187+
All five firmware targets, including ESP32-C3 and Raspberry Pi
188+
Pico 2 W, are staged and pending hardware validation.
189+
</>
190+
) : null}
165191
</p>
166192
<div className="button-row">
167193
<Link className="button button--primary" href="/app">
@@ -357,7 +383,9 @@ export default function HomePage() {
357383
))}
358384
</div>
359385
</div>
360-
{waveshareLcd147b ? <WaveshareBoardPhoto showInstallerLink /> : null}
386+
{releaseHasWaveshareProfile ? (
387+
<WaveshareBoardPhoto showInstallerLink />
388+
) : null}
361389
</div>
362390
</section>
363391

‎tools/web/src/app/support/page.tsx‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,15 @@ function qualifiedProfileList(profileIds: readonly string[]) {
4949
export default function SupportPage() {
5050
const firmwareRelease = firmwareReleaseSelectedAtBuild();
5151
const publicBeta = firmwareRelease?.deployment === "public-beta";
52+
const candidate = firmwareRelease?.deployment === "candidate";
5253
const qualifiedPublic =
5354
firmwareRelease !== null &&
5455
releaseIncludesWaveshareLcd147b(firmwareRelease);
55-
const esp32C3Available =
56-
qualifiedPublic &&
57-
firmwareRelease.profiles.some(({ id }) => id === "esp32-c3-4mb");
56+
// Derived from the release profile set so the note never contradicts the
57+
// /flash installer's offered targets.
58+
const esp32C3Available = Boolean(
59+
firmwareRelease?.profiles.some(({ id }) => id === "esp32-c3-4mb"),
60+
);
5861

5962
return (
6063
<main id="main-content">
@@ -97,6 +100,13 @@ export default function SupportPage() {
97100
. The Waveshare image alone includes its TFT runtime and
98101
fresh-install splash.
99102
</>
103+
) : candidate ? (
104+
<>
105+
Protected candidate v{firmwareRelease.version} is staged
106+
for access-controlled qualification; hardware validation
107+
is pending on every included profile before a public
108+
release.
109+
</>
100110
) : (
101111
<>
102112
The firmware installer is currently unavailable. Check

‎tools/web/src/lib/site.ts‎

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,61 +41,80 @@ const firmwareTargetDefinitions = [
4141
id: "esp32-4mb",
4242
target: "Classic ESP32",
4343
constraint: "4 MiB external SPI flash · no PSRAM assumed",
44-
planned: false,
4544
},
4645
{
4746
id: "esp32-s3-n16r8",
4847
target: "ESP32-S3 N16R8",
4948
constraint: "16 MiB flash · 8 MiB Octal PSRAM",
50-
planned: false,
5149
},
5250
{
5351
id: "waveshare-esp32-s3-lcd-147b",
5452
target: "Waveshare ESP32-S3-LCD-1.47B",
5553
constraint: "Exact B version · 16 MiB flash · 8 MiB Octal PSRAM",
56-
planned: false,
5754
},
5855
{
5956
id: "esp32-c3-4mb",
6057
target: "ESP32-C3",
6158
constraint: "4 MiB external SPI flash · no PSRAM assumed",
62-
planned: true,
59+
},
60+
{
61+
id: "rpi-pico2-w",
62+
target: "Raspberry Pi Pico 2 W",
63+
constraint: "RP2350 + CYW43439 · UF2 / BOOTSEL",
6364
},
6465
] as const;
6566

67+
// Ports whose availability is derived from the selected release's profile
68+
// set: absent from the release, they are presented as planned, never as a
69+
// silently missing target.
70+
const deferredUntilIncluded = new Set<string>(["esp32-c3-4mb", "rpi-pico2-w"]);
71+
6672
export function firmwareTargetsForRelease(
6773
release: FirmwareReleaseDescriptor | null,
6874
) {
6975
const includesWaveshareLcd147b = releaseIncludesWaveshareLcd147b(release);
70-
const hasProspectiveProfileSet = Boolean(
76+
const validProfileSet = Boolean(
7177
release &&
72-
release.deployment === "candidate" &&
73-
hasExactFirmwareProfileDescriptors(release.version, release.profiles),
78+
(release.deployment === "public-beta" ||
79+
hasExactFirmwareProfileDescriptors(release.version, release.profiles)),
7480
);
7581

7682
return firmwareTargetDefinitions
83+
.map((target) => ({
84+
target,
85+
included: Boolean(
86+
validProfileSet && release?.profiles.some(({ id }) => id === target.id),
87+
),
88+
}))
7789
.filter(
78-
(target) =>
79-
target.id !== "waveshare-esp32-s3-lcd-147b" ||
80-
includesWaveshareLcd147b ||
81-
hasProspectiveProfileSet,
90+
({ target, included }) =>
91+
target.id !== "waveshare-esp32-s3-lcd-147b" || included,
8292
)
83-
.map((target) => {
93+
.map(({ target, included }) => {
94+
const planned = !included && deferredUntilIncluded.has(target.id);
95+
const includesWaveshareProfile =
96+
target.id === "esp32-s3-n16r8"
97+
? Boolean(
98+
validProfileSet &&
99+
release?.profiles.some(
100+
({ id }) => id === "waveshare-esp32-s3-lcd-147b",
101+
),
102+
)
103+
: false;
84104
let status = "Installer unavailable";
85-
if (target.planned) {
105+
if (planned) {
86106
status = "Planned · installer unavailable pending exact-profile HIL";
87-
} else if (release?.deployment === "public-beta") {
107+
} else if (included && release?.deployment === "public-beta") {
88108
status = `v${release.version} hardware-tested beta · browser install/recovery passed · release qualification pending`;
89-
} else if (release && includesWaveshareLcd147b) {
109+
} else if (included && release && includesWaveshareLcd147b) {
90110
status = `v${release.version} qualified public release`;
91-
} else if (release?.deployment === "candidate") {
111+
} else if (included && release?.deployment === "candidate") {
92112
status = `v${release.version} protected candidate · HIL pending`;
93113
}
94-
const targetName =
95-
includesWaveshareLcd147b && target.id === "esp32-s3-n16r8"
96-
? `${target.target} · lean generic`
97-
: target.target;
98-
return { ...target, target: targetName, status };
114+
const targetName = includesWaveshareProfile
115+
? `${target.target} · lean generic`
116+
: target.target;
117+
return { ...target, target: targetName, planned, status };
99118
});
100119
}
101120

0 commit comments

Comments
 (0)