diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index ed56678..5398220 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -31,10 +31,61 @@ body: validations: required: true - type: input - id: hardware + id: profile attributes: - label: Hardware and platform - description: Exact board/profile and iPadOS, Android, browser, or desktop version + label: Exact installer profile ID + description: For installer problems, use the exact profile ID shown on /flash; otherwise enter "Not installer-related." + validations: + required: true + - type: input + id: module + attributes: + label: Exact board model and module marking + description: Copy the board model and the text printed on the module; enter "Not applicable" only when no board is involved. + validations: + required: true + - type: input + id: memory + attributes: + label: Memory configuration + description: Flash capacity, PSRAM capacity, and PSRAM type (Octal, Quad, none, or unknown). + validations: + required: true + - type: input + id: browser + attributes: + label: Browser + description: Browser name and exact version; enter "Not applicable" when the browser is not involved. + validations: + required: true + - type: input + id: operating_system + attributes: + label: Desktop operating system + description: Desktop operating system and exact version; enter "Not applicable" when the installer is not involved. + validations: + required: true + - type: input + id: installer_stage + attributes: + label: Failed installer stage + description: For example page load, browser check, profile selection, artifact verification, port selection, erase, write, verification, first boot, or recovery; otherwise enter "Not installer-related." + validations: + required: true + - type: input + id: tablet + attributes: + label: Exact tablet or device model + description: Name the iPad or Android device used with the app; enter "Not applicable" only when the app is not involved. + validations: + required: true + - type: input + id: tablet_os + attributes: + label: Tablet operating system + description: Tablet operating system and exact version (iPadOS or Android); enter "Not applicable" only when the app is not involved. + validations: + required: true - type: textarea id: steps attributes: diff --git a/README.md b/README.md index ffea44a..d508b3c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ compatible microcontroller board over Bluetooth Low Energy. Its normal workflow needs no USB serial connection, Wi-Fi onboarding, cloud account, or telemetry. -- Website and browser installer: [pyble.dev](https://pyble.dev) +- Website and browser-installer status: [pyble.dev](https://pyble.dev) - iPad external beta: [join with TestFlight](https://testflight.apple.com/join/yU4e8s6d) - License: [MIT](LICENSE) @@ -27,7 +27,7 @@ telemetry.
- Actual PyBLE app: a GPIO 48 NeoPixel Blocks program and its generated MicroPython on the pictured ESP32-S3 board. + Actual PyBLE app in landscape: GPIO 48 NeoPixel Blocks beside the generated MicroPython.
## What works @@ -62,16 +62,17 @@ BLE GATT peripheral. It supports: - board naming and identify support; and - upstream MicroPython’s standard `neopixel` module. -The public browser installer currently offers qualified images for: +The public browser installer is currently unavailable pending v0.4.2 HIL on +both exact current profiles: -| Installer profile | Typical target | Availability | -| ----------------- | ---------------------------------- | ------------------------------------------- | -| `esp32-4mb` | Classic ESP32, 4 MB flash | Available | -| `esp32-s3-n16r8` | ESP32-S3, 16 MB flash / 8 MB PSRAM | Available | -| `esp32-c3-4mb` | ESP32-C3, 4 MB flash | Source target; public installer pending HIL | +| Installer profile | Exact target constraint | Public status | +| ----------------- | ------------------------------------------------------------ | --------------------------------------------------- | +| `esp32-4mb` | Classic ESP32, 4 MiB external SPI flash; no PSRAM assumed | v0.4.2 HIL pending; installer unavailable | +| `esp32-s3-n16r8` | ESP32-S3, 16 MiB flash / 8 MiB Octal PSRAM; N16R8-class only | v0.4.2 HIL pending; installer unavailable | +| `esp32-c3-4mb` | ESP32-C3, 4 MiB external SPI flash; no PSRAM assumed | Planned; no public image; exact-profile HIL pending | -These are the initial validated ports, not a chip-family allowlist. A future -board is compatible when it has a maintained PyBLE agent port, BLE GATT +These are the initial port targets, not a chip-family allowlist. A future board +is compatible when it has a maintained PyBLE agent port, BLE GATT peripheral support, adequate resources, PBLE/1 conformance, recovery testing, and hardware-validation evidence. Stock MicroPython plus generic Bluetooth hardware is not sufficient by itself. @@ -102,14 +103,17 @@ shared conformance corpus, documentation, and CI atomically. ## Try PyBLE -1. Open [pyble.dev/flash](https://pyble.dev/flash) in desktop Chrome or Edge. -2. Select the exact supported profile for your board and flash the qualified - agent firmware. Flashing erases the board; review the installer warning and - back up files first. -3. Install the iPad beta from +1. Install the iPad beta from [TestFlight](https://testflight.apple.com/join/yU4e8s6d), or build the Flutter app locally. -4. Open PyBLE, scan for the board, connect, and run an example. +2. Check [pyble.dev/flash](https://pyble.dev/flash) in desktop Chrome or Edge. + The public installer is currently unavailable pending v0.4.2 HIL. Wait for + that page to show an active release version, your exact profile, and an + enabled install action. +3. Only after that gate opens, back up the board, confirm its exact memory + profile, and use the one-time wired installer. Flashing erases the board. +4. Open PyBLE, scan for the provisioned board, connect, and run an example over + BLE. See [support and troubleshooting](https://pyble.dev/support) for browser, Bluetooth, and recovery requirements. diff --git a/docs/specifications/website.md b/docs/specifications/website.md index 23dc0fb..802ed3f 100644 --- a/docs/specifications/website.md +++ b/docs/specifications/website.md @@ -132,6 +132,40 @@ platform cropping can make it unreliable. A separate local square TestFlight card MAY include the exact invitation QR, visible destination, and plain-text instructions. +### 3.4 Pre-activation release claims and support intake + +Until the first v0.4.2 public firmware selector passes the complete gate in §7, +the repository README and home page MUST say that the browser installer is +unavailable pending v0.4.2 HIL on both exact current profiles. They MUST NOT +describe either profile or its browser image as released, available, or +qualified. The home-page target cards MUST identify the profiles and constraints +as `esp32-4mb` (classic ESP32, 4 MiB external SPI flash, no PSRAM assumed) and +`esp32-s3-n16r8` (ESP32-S3, 16 MiB flash, 8 MiB **Octal** PSRAM), and give each +the truthful pending-HIL/unavailable state. `esp32-c3-4mb` remains a separate +planned, unavailable profile. + +README getting-started instructions MUST gate destructive flashing on `/flash` +showing an active version, exact profile, and enabled install action. While the +installer is unavailable, they MUST NOT instruct a reader to select or flash a +supposedly qualified public image. A real-app capture caption MUST describe only +what is visible; it MUST NOT claim that a physical board is pictured when the +capture shows only the app. + +While the installer is unavailable, the wide social card MUST describe the +workflow as one-time USB setup followed by everyday use over BLE. It MUST NOT +advertise an enabled web flasher; it MAY explicitly label firmware HIL as +pending. Its mechanically rendered PNG and authored SVG MUST remain paired by +reviewed content and exact-dimension tests. + +The support route MUST link directly to the preferred GitHub bug template at +`https://github.com/PyBLE-dev/PyBLE/issues/new?template=bug.yml`. Installer +intake MUST request the exact profile ID, board/model and module marking, flash +capacity, PSRAM capacity and type, browser name/version, desktop operating +system/version, failed installer stage, redacted error text, exact tablet/device +model, and tablet operating system/version (iPadOS or Android). The issue +template and support-page checklist MUST agree on those fields and remind users +to remove secrets and personal identifiers. + ## 4. Brand and visual contract The canonical prompt-chip SVG in `app/assets/branding/` is the source asset. A diff --git a/tests/publication/test_public_claims.py b/tests/publication/test_public_claims.py new file mode 100644 index 0000000..e2b0529 --- /dev/null +++ b/tests/publication/test_public_claims.py @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: MIT +# Part of PyBLE (https://pyble.dev) — see /LICENSE. + +from __future__ import annotations + +import unittest +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[2] + + +def markdown_section(document: str, heading: str) -> str: + marker = f"## {heading}\n" + start = document.index(marker) + len(marker) + end = document.find("\n## ", start) + return document[start:] if end < 0 else document[start:end] + + +class PublicClaimsTest(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8") + cls.bug_template = ( + REPO_ROOT / ".github" / "ISSUE_TEMPLATE" / "bug.yml" + ).read_text(encoding="utf-8") + + def test_readme_is_truthful_before_v042_hil_completes(self) -> None: + firmware = markdown_section(self.readme, "What works") + + self.assertIn( + "public browser installer is currently unavailable pending v0.4.2 HIL", + firmware, + ) + self.assertIn("`esp32-4mb`", firmware) + self.assertIn("Classic ESP32, 4 MiB external SPI flash", firmware) + self.assertIn("`esp32-s3-n16r8`", firmware) + self.assertIn("16 MiB flash / 8 MiB Octal PSRAM", firmware) + self.assertNotIn("currently offers qualified images", firmware) + self.assertNotIn("| Available", firmware) + + def test_readme_caption_describes_only_the_visible_app(self) -> None: + caption_start = self.readme.index("Actual PyBLE app") + caption_end = self.readme.index("", caption_start) + caption = self.readme[caption_start:caption_end] + + self.assertIn("in landscape", caption) + self.assertIn("GPIO 48 NeoPixel Blocks", caption) + self.assertIn("generated MicroPython", caption) + self.assertNotRegex(caption, r"(?i)pictured|board|module") + + def test_readme_try_steps_are_gated_on_an_active_installer(self) -> None: + try_section = markdown_section(self.readme, "Try PyBLE") + + self.assertIn("currently unavailable pending v0.4.2 HIL", try_section) + self.assertIn("active release version", try_section) + self.assertIn("enabled install action", try_section) + self.assertNotRegex(try_section, r"(?is)select .*qualified\s+agent firmware") + + def test_bug_template_collects_the_exact_installer_diagnostics(self) -> None: + for field_id in ( + "profile", + "module", + "memory", + "browser", + "operating_system", + "installer_stage", + "tablet", + "tablet_os", + ): + self.assertIn(f" id: {field_id}\n", self.bug_template) + + for wording in ( + "Exact installer profile ID", + "Exact board model and module marking", + "Flash capacity, PSRAM capacity, and PSRAM type", + "Browser name and exact version", + "Desktop operating system and exact version", + "Failed installer stage", + "Exact tablet or device model", + "Tablet operating system and exact version", + ): + self.assertIn(wording, self.bug_template) + + self.assertRegex(self.bug_template, r"(?i)remove.*(?:secret|credential)") + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/web/public/social/pyble-beta-og-1200x630.png b/tools/web/public/social/pyble-beta-og-1200x630.png index e801659..875f61d 100644 Binary files a/tools/web/public/social/pyble-beta-og-1200x630.png and b/tools/web/public/social/pyble-beta-og-1200x630.png differ diff --git a/tools/web/public/social/pyble-beta-og-1200x630.svg b/tools/web/public/social/pyble-beta-og-1200x630.svg index 23c229e..09f6d03 100644 --- a/tools/web/public/social/pyble-beta-og-1200x630.svg +++ b/tools/web/public/social/pyble-beta-og-1200x630.svg @@ -11,8 +11,9 @@ >PyBLE is a free, tablet-first IDE designed for boards that run - MicroPython and support Bluetooth Low Energy. The current firmware - release supports qualified classic ESP32 and ESP32-S3 module - profiles. ESP32-C3 and more microcontroller families remain - planned. + MicroPython and support Bluetooth Low Energy. Public v0.4.2 + firmware is pending HIL for the exact esp32-4mb and esp32-s3-n16r8 + profiles. The public browser installer stays unavailable until + both exact profiles pass HIL. ESP32-C3 and more microcontroller + families remain planned.
External testing is open
- Install the free iPad beta through Apple TestFlight. Then use - desktop Chrome to provision a supported board and start coding - over Bluetooth Low Energy. + Install the free iPad beta through Apple TestFlight now. Public + board provisioning will open only after v0.4.2 passes HIL on both + exact release profiles; after that one-time USB setup, everyday + coding runs over Bluetooth Low Energy.
diff --git a/tools/web/src/app/support/page.tsx b/tools/web/src/app/support/page.tsx index 0812d90..9af5fbf 100644 --- a/tools/web/src/app/support/page.tsx +++ b/tools/web/src/app/support/page.tsx @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Part of PyBLE (https://pyble.dev) — see /LICENSE. -import { MailIcon } from "@/components/icons"; +import { ExternalIcon, MailIcon } from "@/components/icons"; import { PageIntro } from "@/components/page-intro"; import { pageMetadata, siteConfig } from "@/lib/site"; @@ -13,11 +13,15 @@ export const metadata = pageMetadata({ }); const diagnosticItems = [ - "Board and chip family", + "Exact installer profile ID (or “not installer-related”)", + "Exact board model and module marking", + "Flash capacity, PSRAM capacity, and PSRAM type", + "Browser name/version and desktop OS name/version", + "Failed installer stage and redacted error text", + "Exact tablet or device model", + "Tablet OS: iPadOS or Android name/version", "PyBLE app and agent versions", - "iPadOS or Android version", "The exact steps that caused the problem", - "Relevant console text and a screenshot", ] as const; export default function SupportPage() { @@ -38,12 +42,12 @@ export default function SupportPage() {- The public installer supports only esp32-4mb and - esp32-s3-n16r8. ESP32-C3 is not currently available. Use the - reviewed image supplied for your exact target; this initial - step uses a cable. + The public installer is unavailable while v0.4.2 HIL runs + for esp32-4mb and esp32-s3-n16r8. ESP32-C3 is not currently + available. Wait for the installer status to show an active + release and enabled action; this initial step uses a cable.