Skip to content

Commit 98c8722

Browse files
committed
[green] Name pre-HIL firmware profiles as candidates
Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent 011819f commit 98c8722

9 files changed

Lines changed: 52 additions & 45 deletions

File tree

docs/specifications/firmware.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,13 @@ MUST NOT require a known-chip allowlist.
118118
The measurement method is frozen in
119119
[firmware/specs.md §5.3](firmware/specs.md#53-footprint-gates-nfr-fp);
120120
numeric values remain provisional until derived from retained baseline samples.
121-
The current pre-v1 qualification is profile-scoped:
121+
The v0.4.2 candidate qualification scope is profile-scoped:
122122

123123
| Profile | Current numeric status | Release effect |
124124
|---|---|---|
125-
| `esp32-4mb` | Measure, derive, freeze, and verify on the owned exact profile | Required for the current pre-v1 installer |
126-
| `esp32-s3-n16r8` | Measure, derive, freeze, and verify on the owned exact N16R8 profile | Required for the current pre-v1 installer |
127-
| `esp32-c3-4mb` | Deferred; no current threshold or HIL row | Blocks C3 enablement and v1.0, but not the two-profile pre-v1 release |
125+
| `esp32-4mb` | Measure, derive, freeze, and verify on the owned exact profile | Required before v0.4.2 candidate qualification and installer activation |
126+
| `esp32-s3-n16r8` | Measure, derive, freeze, and verify on the owned exact N16R8 profile | Required before v0.4.2 candidate qualification and installer activation |
127+
| `esp32-c3-4mb` | Deferred; no current threshold or HIL row | Blocks C3 enablement and v1.0, but not qualification of the two-profile candidate |
128128

129129
The enforced metrics are:
130130

docs/specifications/firmware/browser-flashing.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ BLE and PBLE/1.
3737

3838
## 1. Release image profiles
3939

40-
The current pre-v1 public bundle contains exactly these two qualified
41-
**provisioning image profiles**:
40+
The v0.4.2 release candidate targets exactly these two **provisioning image
41+
profiles**. Neither becomes a qualified public profile until the complete
42+
reproducibility, license, exact-byte HIL, and activation gate passes:
4243

4344
| Profile ID | ESP Web Tools `chipFamily` | Required target configuration | ESP image silicon window (`min_chip_rev_full``max_chip_rev_full`) | Merge settings | Browser image and component map |
4445
|---|---|---|---|---|---|
@@ -163,7 +164,7 @@ as immutable inputs to one release candidate. Candidate-freezing MUST happen
163164
before the two clean release builds, license audit, candidate packaging,
164165
protected-site staging, or HIL. It is an input-selection state only: it does
165166
**not** assert that the pins work on hardware and does not approve them for a
166-
public release. Exact-profile HIL on both current release profiles,
167+
public release. Exact-profile HIL on both current candidate profiles,
167168
`esp32-4mb` and `esp32-s3-n16r8`, remains the pre-v1 public-release approval
168169
gate.
169170

@@ -336,7 +337,7 @@ one build for its owning profile. For example,
336337

337338
`<version>` above is a template substitution, not literal released JSON.
338339
The `esp32-4mb` manifest has the same shape and exactly one `ESP32` build with
339-
offset `4096`. There is no C3 manifest in the current release. The website MUST
340+
offset `4096`. There is no C3 manifest in the current candidate. The website MUST
340341
set the custom element's manifest URL to the verified manifest for the selected
341342
profile only. It MUST NOT pass an all-family catalog to ESP Web Tools or change
342343
manifests after the browser has selected a serial device.
@@ -389,7 +390,7 @@ beside their metadata:
389390
UTC `built_at`;
390391
- provenance: full PyBLE commit and clean state; MicroPython ref/commit;
391392
ESP-IDF ref/commit; patch count; runner and compiler/tool versions;
392-
- one entry for each current release profile in the first table of §1,
393+
- one entry for each current candidate profile in the first table of §1,
393394
including profile ID, `chip_family`,
394395
flash/PSRAM requirements, flash mode/frequency, required
395396
`silicon_revision.minimum_full` and `silicon_revision.maximum_full` integers
@@ -457,7 +458,7 @@ public notice.
457458
The conservative build audit runs against all six authoritative ESP-IDF
458459
descriptions: application and bootloader `project_description.json` for each
459460
of the three initial build targets. This preserves the v1 three-target build
460-
and license gate even while the pre-v1 public bundle contains two profiles.
461+
and license gate even while the pre-v1 candidate bundle targets two profiles.
461462
The released notice MUST classify as redistributed only the dependency union
462463
of the two packaged profiles; C3-only observations remain retained review
463464
evidence and MUST NOT be represented as a shipped C3 image or shipped profile.
@@ -1089,7 +1090,7 @@ Automated release tests MUST cover:
10891090
- static-export and candidate/production-origin retrieval of every versioned
10901091
byte.
10911092

1092-
One HIL record MUST be completed for each of the two exact current release
1093+
One HIL record MUST be completed for each of the two exact current candidate
10931094
profiles using the final, hash-locked release candidate. The report contains
10941095
exactly one embedded JSON object marked `PYBLE_HIL_RECORDS_V2`; a V1 marker,
10951096
an additional marker, or keys not defined below are invalid.

docs/specifications/firmware/specs.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Where this document and [TDD.md](TDD.md) touch the same topic, this document win
9090
- **Workspace jail** — the constraint that PBLE/1 file commands may only read/write within `fs_root`.
9191
- **Runner** — the task that executes user code (file or inline source).
9292
- **HIL** — hardware-in-the-loop testing on every exact real-hardware profile
93-
claimed by a release. The current pre-v1 release matrix is exactly
93+
claimed by a release. The current pre-v1 candidate matrix is exactly
9494
`esp32-4mb` and `esp32-s3-n16r8`; the v1.0 matrix additionally requires
9595
`esp32-c3-4mb` (PRD §1B.3, §10.12).
9696
- **Frozen-Python agent** — agent modules baked into the firmware image as `.py` (frozen at build); the recommended first implementation.
@@ -251,7 +251,7 @@ are screenless.
251251
- **FR-LIB-1** — Every `esp32`, `esp32-s3`, and `esp32-c3` firmware image MUST make the pinned upstream MicroPython `neopixel.NeoPixel` API importable offline by user file/source runs and after a soft reboot. MUST (*source: PRD §9.8, §11.3; verify: resolved-manifest/build/HIL; story: F-24/A-31*)
252252
- **FR-LIB-2** — The module MUST be selected from the pristine pinned MicroPython/micropython-lib tree through each target's frozen manifest; PyBLE MUST NOT copy, fork, patch, or replace it with a custom WS2812 driver. MUST (*source: PRD §1A, §10.9, §10.10; verify: build/structure; story: F-24*)
253253
- **FR-LIB-3** — Bundling NeoPixel MUST NOT add an agent GPIO abstraction, PBLE/1 opcode/capability, board/onboard-LED name, pin/count/colour default, or target-specific user-code routing. GPIO, pixel count, index, colour, timing, and physical suitability remain explicit user-program/runtime concerns. MUST (*source: PRD §9.8, §11.3; verify: unit/no-leak/HIL; story: F-24/A-31*)
254-
- **FR-LIB-4** — Release validation MUST resolve exactly one `neopixel.py` for each of the three build targets, record the per-target firmware-size delta, and run a runtime import smoke on every exact profile included in that release. The current pre-v1 runtime matrix is the two profiles in §2.2; `esp32-c3-4mb` runtime smoke remains required before that profile is enabled and before v1.0. Any visual LED smoke MUST take an operator-supplied GPIO, use a bounded dim sequence, and turn the pixel off on exit. MUST (*source: PRD §10.11, §10.13, §13.3; verify: build/size/HIL; story: F-24*)
254+
- **FR-LIB-4** — Release validation MUST resolve exactly one `neopixel.py` for each of the three build targets, record the per-target firmware-size delta, and run a runtime import smoke on every exact profile included in that release. The current pre-v1 candidate runtime matrix is the two profiles in §2.2; `esp32-c3-4mb` runtime smoke remains required before that profile is enabled and before v1.0. Any visual LED smoke MUST take an operator-supplied GPIO, use a bounded dim sequence, and turn the pixel off on exit. MUST (*source: PRD §10.11, §10.13, §13.3; verify: build/size/HIL; story: F-24*)
255255

256256
This NeoPixel contract applies to the three initial ESP32-family images.
257257
A future platform port MUST NOT claim equivalent support until it validates the
@@ -283,7 +283,7 @@ upstream package and required runtime primitive for that target.
283283
> and evidence schema before any threshold is selected. It does not invent or
284284
> claim a numeric threshold.
285285
286-
The current pre-v1 qualification set is exactly, and in this order,
286+
The current pre-v1 candidate qualification set is exactly, and in this order,
287287
`esp32-4mb` and `esp32-s3-n16r8`. Each MUST have a complete numeric policy and
288288
final-candidate HIL record before the current public installer can be enabled.
289289
`esp32-c3-4mb` MUST NOT have a threshold entry or HIL row in this pre-v1
@@ -322,7 +322,7 @@ matrix remains all three profiles.
322322
story: X-03, F-13/14)*
323323
- **NFR-FP-CLOSE** — Every exact profile included in a release is
324324
**release-blocking** until all of its thresholds are frozen and its
325-
hash-locked final-candidate evidence passes. For the current pre-v1 release
325+
hash-locked final-candidate evidence passes. For the current pre-v1 candidate
326326
this means exactly the two profiles above. The still-open C3 portion blocks
327327
any C3 release and v1.0, but it does not block an otherwise-qualified
328328
two-profile pre-v1 release. — *(source: PRD §10.12, §10.13, §7.1; verify:
@@ -586,8 +586,9 @@ This is software-level safety of the IDE/agent, **not** hardware/actuator safety
586586
bundle at the canonical versioned same-origin path. A v0.x mirror is optional
587587
and every corresponding file and byte MUST be identical when one is
588588
published. v1.0 and later MUST additionally publish the matching
589-
byte-identical GitHub Release. The current pre-v1 bundle MUST cover exactly
590-
the two qualified profiles; v1.0 MUST restore three-target release parity. —
589+
byte-identical GitHub Release. The current pre-v1 candidate bundle MUST target
590+
exactly the two profiles and MUST NOT become public until both qualify; v1.0
591+
MUST restore three-target release parity. —
591592
*(source: PRD §10.12, §18.2,
592593
[browser-flashing §3](browser-flashing.md#3-same-origin-versioned-layout);
593594
verify: build, release; story: X-11)*
@@ -664,7 +665,7 @@ This is software-level safety of the IDE/agent, **not** hardware/actuator safety
664665
verification MUST inspect generated frozen content or the running image, not
665666
stale intermediate `.mpy` files. — *(source: FR-LIB, ADR-0018; verify:
666667
build/HIL; story: F-24)*
667-
- **BLD-17** — The current pre-v1 browser release MUST expose exactly
668+
- **BLD-17** — The current pre-v1 browser candidate MUST target exactly
668669
`esp32-4mb` and `esp32-s3-n16r8`, with the memory qualifications, merge
669670
settings, browser-image base offsets, and component offsets frozen in
670671
[browser-flashing §1](browser-flashing.md#1-release-image-profiles). Family
@@ -762,7 +763,7 @@ These are tracked, release-blocking where noted; they MUST be closed before the
762763

763764
- **OI-1 — Per-profile resource numbers pending HIL.** The measurement method,
764765
exact current scope, evidence contract, and threshold derivation are frozen
765-
in §5.3. Numeric thresholds remain open. The current pre-v1 portion closes
766+
in §5.3. Numeric thresholds remain open. The current pre-v1 candidate portion closes
766767
only when `esp32-4mb` and `esp32-s3-n16r8` each have committed
767768
evidence-derived policy values and passing final-candidate HIL. That state
768769
MUST be described as **“qualified for the current two-profile pre-v1
@@ -776,7 +777,7 @@ These are tracked, release-blocking where noted; they MUST be closed before the
776777
Before release builds and HIL, its exact committed bytes MUST be selected as
777778
candidate-frozen immutable inputs. That selection is not hardware approval:
778779
the exact candidate MUST still pass HIL on every exact profile included in
779-
that release. The current pre-v1 set is the two profiles in §5.3; C3 remains
780+
that release. The current pre-v1 candidate set is the two profiles in §5.3; C3 remains
780781
mandatory before C3 enablement and before v1.0. A pin change creates a new
781782
candidate and resets all candidate-bound evidence. — *(verify: build, HIL)*
782783
- **OI-3 — Frozen → native split point TBD.** The agent starts frozen-Python; the decision of which hot paths (BLE I/O, framing, file chunking) move to a native `USER_C_MODULE`, and on which chip the budget forces it, is open and determined by HIL footprint/throughput measurement ([firmware.md §2](../firmware.md#2-agent-base-native-vs-frozen), [PRD §10.2](../prd.md)). The PBLE/1 wire contract MUST NOT change across the move (NFR-MAINT-3). — *(verify: size, conformance, HIL)*

docs/specifications/prd.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Each story selects the applicable categories; the protocol and firmware stories
159159
- **Hardware-in-the-loop (HIL)** — on every exact profile claimed by the
160160
release: connect, `DEVICE_INFO`, run/stop, console streaming, and a clean
161161
multi-file upload without dropping the link, plus resume-on-reconnect and
162-
the resource measurements above. The current pre-v1 matrix is exactly
162+
the resource measurements above. The current pre-v1 candidate matrix is exactly
163163
`esp32-4mb` plus `esp32-s3-n16r8`; v1.0 additionally requires
164164
`esp32-c3-4mb`. A milestone is gated by a working HIL demo, not by merged
165165
code alone.
@@ -839,7 +839,7 @@ Each successful per-target build MUST emit a flashable artifact set ([firmware.m
839839
matrix. An unqualified profile MUST be absent from release metadata,
840840
artifacts, selection, and recovery commands and shown as unavailable, never
841841
silently marked supported.
842-
- The current pre-v1 release set is exactly `esp32-4mb` and
842+
- The current pre-v1 candidate set is exactly `esp32-4mb` and
843843
`esp32-s3-n16r8`; `esp32-c3-4mb` remains unavailable pending exact-profile
844844
real-hardware validation. Re-enabling it requires a new SemVer candidate and
845845
immutable bundle.
@@ -855,7 +855,7 @@ numbers are frozen. The detailed method, exact workload, metric meanings,
855855
rounding formulas, and evidence contract are normative in
856856
[firmware/specs.md §5.3](firmware/specs.md#53-footprint-gates-nfr-fp).
857857

858-
| Gate | Metric and direction | Current pre-v1 profiles | ESP32-C3 / v1.0 |
858+
| Gate | Metric and direction | Current pre-v1 candidate profiles | ESP32-C3 / v1.0 |
859859
|---|---|---|---|
860860
| **FP-FLASH** | Total shipped application-image ceiling plus factory-partition headroom floor | Freeze separately for `esp32-4mb` and `esp32-s3-n16r8` | Remains open for `esp32-c3-4mb`; C3 is the hard constraint |
861861
| **FP-HEAP** | Python GC and internal-IDF current/largest/minimum heap floors after HELLO and transfer workloads | Freeze separately for both included profiles; default-capability `free_mem` is diagnostic only | Must leave usable user-code and control-plane headroom |
@@ -864,7 +864,7 @@ rounding formulas, and evidence contract are normative in
864864

865865
Requirements:
866866

867-
- The current pre-v1 public set is exactly the two profiles in §10.12. Their
867+
- The current pre-v1 candidate set is exactly the two profiles in §10.12. Their
868868
numeric thresholds and hash-locked final-candidate HIL are release-blocking.
869869
`esp32-c3-4mb` MUST remain absent from that release's policy, HIL rows,
870870
artifacts, recovery, and installer selection.
@@ -1101,7 +1101,7 @@ Exact per-package licenses MUST be generated mechanically at build time (not han
11011101
### §15.3 Distribution
11021102

11031103
- The app MUST be distributed **free** on the **Apple App Store** and **Google Play**, at feature parity across iPadOS and Android tablets (see §13.6 and §19). No account, no paywall, no in-app purchase.
1104-
- A browser-based **web flasher** MUST be hosted at `pyble.dev/flash`, built on **esp-web-tools**, with one profile-scoped, single-build manifest per exact profile included in that release (see [firmware.md §6](firmware.md#6-build--distribution)). It MUST allow a user to flash the agent from a supported desktop browser over USB without installing a toolchain, and MUST NOT give ESP Web Tools a multi-family manifest that could override the user's selected profile. The current pre-v1 set is the two profiles in §10.12; C3 is unavailable until separately qualified.
1104+
- A browser-based **web flasher** MUST be hosted at `pyble.dev/flash`, built on **esp-web-tools**, with one profile-scoped, single-build manifest per exact profile included in that release (see [firmware.md §6](firmware.md#6-build--distribution)). It MUST allow a user to flash the agent from a supported desktop browser over USB without installing a toolchain, and MUST NOT give ESP Web Tools a multi-family manifest that could override the user's selected profile. The current pre-v1 candidate set is the two profiles in §10.12; C3 is unavailable until separately qualified.
11051105
- Firmware binaries (`firmware.bin`, bootloader, partition table, profile-scoped
11061106
`manifest.json` files, and `THIRD_PARTY_LICENSES`) MUST be published at the
11071107
canonical immutable `pyble.dev/firmware/v<version>/` path, one set per exact
@@ -1390,7 +1390,7 @@ The entry flow is scan → connect → use, with no QR pairing, no account, and
13901390
These are the production targets the project measures itself against. Numeric
13911391
BLE/throughput targets are validated on hardware for every exact profile
13921392
included in a release and MUST be frozen per profile after measurement. The
1393-
current pre-v1 matrix has two profiles; the v1.0 matrix has all three. Until a
1393+
current pre-v1 candidate matrix has two profiles; the v1.0 matrix has all three. Until a
13941394
profile's values are frozen, they are stated as intent, not asserted.
13951395

13961396
| Metric | Definition | v1.0 target | Status |
@@ -1543,7 +1543,7 @@ The foundational product decisions are resolved and recorded as Architecture Dec
15431543
file MUST first be candidate-frozen as the immutable release-build/HIL
15441544
input; that state is not approval. The same candidate MUST then pass the
15451545
complete exact-profile HIL matrix before its pins and resource gates are
1546-
approved. The current pre-v1 subset is exactly the two profiles in §10.12;
1546+
approved. The current pre-v1 candidate subset is exactly the two profiles in §10.12;
15471547
all three, including C3, are required for v1.0 (§10.9, §17.1, §21.2). A pin
15481548
change creates a new candidate. New ADRs are added if a pin or budget
15491549
changes materially.
@@ -1564,4 +1564,4 @@ New significant decisions MUST be captured as additional ADRs (`docs/decisions/N
15641564
| **Control plane** | The agent's protected layer that owns BLE, the runner, and the filesystem bridge. It MUST NOT be editable by user code; a frozen `while True` in user code MUST NOT be able to wedge BLE or block `STOP`. |
15651565
| **Workspace** | The user's own files on the board — `/main.py`, `/lib/*.py`, `/data/*` (Layer 4). Just programs the agent runs; never the control plane. |
15661566
| **Platform port / target adapter** | Layer-2 integration for a MicroPython target: BLE host, scheduler/interrupt boundary, storage/config, identity, build, and provisioning. The initial ESP32 port uses per-chip board overlays for `esp32` / `esp32-s3` / `esp32-c3`, copied into the upstream tree at build prep so the submodule stays pristine. |
1567-
| **HIL** | Hardware-in-the-loop — validation and measurement performed on a real board (as opposed to host-side or fake-transport tests). Resource and BLE/goodput numbers are frozen only after HIL measurement for every exact profile claimed by a release. The current pre-v1 matrix is `esp32-4mb` plus `esp32-s3-n16r8`; v1.0 additionally requires `esp32-c3-4mb`. |
1567+
| **HIL** | Hardware-in-the-loop — validation and measurement performed on a real board (as opposed to host-side or fake-transport tests). Resource and BLE/goodput numbers are frozen only after HIL measurement for every exact profile claimed by a release. The current pre-v1 candidate matrix is `esp32-4mb` plus `esp32-s3-n16r8`; v1.0 additionally requires `esp32-c3-4mb`. |

0 commit comments

Comments
 (0)