Skip to content

Commit afac582

Browse files
committed
[docs] record five-board screenshot provenance
Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent e76af57 commit afac582

3 files changed

Lines changed: 258 additions & 41 deletions
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<!-- SPDX-License-Identifier: MIT -->
2+
3+
# Tutorial five-board screenshot provenance — 2026-08-28
4+
5+
This record covers the Lenovo-only, five-board app captures prepared for local
6+
review of the ten-part learning path. Technical integrity and privacy review
7+
are complete. Final content approval and production publication remain
8+
separate actions.
9+
10+
## Capture environment
11+
12+
- Capture date: `2026-08-28` (`Asia/Bangkok`; the UTC date was also
13+
`2026-08-28`)
14+
- Physical capture device: `Lenovo TB-J616X`
15+
- ADB serial and transport: `HA1HM0X8` over USB; wireless debugging was not
16+
enabled
17+
- Operating system: `Android 12 (API 31)`
18+
- App surface: `PyBLE 0.2.0 beta`, build `5`
19+
- Capture-only package: `dev.pyble.pyble.tutorialcapture`
20+
- App source revision:
21+
`4df378fc76c919f0e2481eb5b668f14115d38587`
22+
- Capture APK SHA-256:
23+
`ad0a15a5f7f80005aac86f422ac53b888162fbca2b96920f4eacf1f1819fc679`
24+
- PyBLE agent version on every connected board: `0.6.0`
25+
- Raw directory (ignored):
26+
`ScreenShots/tutorials/android/lenovo-tb-j616x/0.2.0-beta/five-boards/`
27+
- Reviewed directory (ignored):
28+
`ScreenShots/tutorials/android/lenovo-tb-j616x/0.2.0-beta/five-boards/reviewed-tutorial-set/`
29+
- Processor: `ImageMagick 7.1.2-21 Q16-HDRI aarch64`
30+
31+
The release-mode capture package used a disposable local signing key and a
32+
capture-only application ID so it could coexist with another installed build.
33+
It is not a distributable release artifact. The key and generated build output
34+
remain outside Git.
35+
36+
No iPad was used in this capture workflow. App installation, interaction, and
37+
ADB capture targeted only the Lenovo tablet. The laptop-side processing and
38+
review used only Lenovo raw inputs; no iPad capture entered the set. The Lenovo
39+
stylus overlay was stopped before every selected raw frame. No selected
40+
derivative contains the stylus affordance.
41+
42+
## Five-board session map and evidence boundary
43+
44+
The stopped discovery frame records exactly five distinct advertisements and
45+
`Scan: Idle`. An advertisement proves only that a nearby PBLE agent advertised;
46+
it does not prove installed firmware-profile bytes. Each connection frame
47+
records a Ready status with board ID and agent version plus a read-only runtime
48+
token.
49+
50+
| Advertisement / board ID | Maintained physical-session context | Captured state | Captured runtime token | Evidence boundary |
51+
| --- | --- | --- | --- | --- |
52+
| `PyBLE-5646` / `5646` | Generic ESP32-S3 N16R8, explicitly confirmed by the user | `Ready` / agent `0.6.0` | `esp32-s3` | The user-supplied physical context identifies this board; the runtime token alone is not generic-profile proof. |
53+
| `PyBLE-8C9E` / `8C9E` | Generic/classic ESP32 session | `Ready` / agent `0.6.0` | `esp32` | The app does not prove flash capacity, carrier, pin map, or installed profile bytes. |
54+
| `PyBLE-C81A` / `C81A` | Generic ESP32-C3 session | `Ready` / agent `0.6.0` | `esp32-c3` | The app does not prove flash capacity, carrier, pin map, or installed profile bytes. |
55+
| `PyBLE-DA86` / `DA86` | Waveshare ESP32-S3-LCD-1.47B physical-session context | `Ready` / agent `0.6.0` | `esp32-s3` | The maintained physical-session context identifies the exact board; the runtime token alone does not prove the carrier or Waveshare profile. |
56+
| `PyBLE-3DCB` / `3DCB` | Raspberry Pi Pico 2 W physical-session context | `Ready` / agent `0.6.0` | `rpi-pico2-w` | Exact-board/profile evidence remains the physical marking and installer record, not the token alone. |
57+
58+
The `5646` and `DA86` runtime derivatives intentionally have identical pixels
59+
and the same SHA-256. That is expected evidence: both sessions report only
60+
`esp32-s3` at this layer, so the app cannot distinguish their provisioning
61+
profiles. The paired Ready and runtime derivatives are composed by semantic
62+
HTML/CSS; no raster collage was produced.
63+
64+
These observations are tutorial-documentation evidence only. They are not
65+
PBLE conformance, firmware release qualification, installed-byte proof, or
66+
GPIO, display, wiring, electrical, or other hardware-in-the-loop evidence. No
67+
GPIO or display behavior was exercised or qualified during this capture pass.
68+
69+
## Deterministic processing
70+
71+
[`process-tutorial-captures.sh`](../../tools/web/scripts/process-tutorial-captures.sh)
72+
validated all 13 distinct raw images as one 2000×1200, 8-bit PNG each and
73+
produced 18 derivatives:
74+
75+
| Derivative class | Distinct raw frames | Derivatives | Exact crop |
76+
| --- | ---: | ---: | --- |
77+
| Full app frame | 8 | 8 | `2000x1092+0+36` |
78+
| Connected Ready status | 5 | 5 | `400x84+0+36` |
79+
| Connected read-only runtime panel | Same 5 connected frames | 5 | `512x390+1488+330` |
80+
| Total | 13 | 18 | Three fixed geometries |
81+
82+
The full-frame crop removes 36 pixels of Android status bar from the top and
83+
72 pixels of Android navigation area from the bottom. The processor crops the
84+
two identity regions independently from each connection raw, strips metadata,
85+
forces 8-bit PNG output, excludes date/time chunks, and uses fixed PNG
86+
compression settings. It does not resize, annotate, blur, recolor, generate,
87+
or retouch app pixels. Every output passed an exact crop comparison with zero
88+
changed pixels.
89+
90+
The review directory contains an 18-row `SHA256SUMS`, a deduplicated 13-row
91+
`SOURCE_SHA256SUMS`, and the 18-row `tutorial-captures.tsv` used for the table
92+
below. Reviewed filenames contain the app version, build, stable key, and first
93+
12 characters of the reviewed digest.
94+
95+
## Interaction, writes, and cleanup
96+
97+
- The five-board scan was allowed to settle, then stopped before capture. It
98+
showed the five intended advertisements and `Scan: Idle`.
99+
- `5646` was used for read-only identity and GitHub browsing/review frames. No
100+
GitHub file was downloaded to that board.
101+
- On `8C9E`, `/tutorial-capture/hello.py` was created with 26 bytes and run
102+
once. The program was a hardware-free Console greeting. Two empty disposable
103+
files, `/tutorial-capture/delete_me_one.py` and
104+
`/tutorial-capture/delete_me_two.py`, were then created for the exact
105+
permanent-delete review. The confirmation shown in the selected frame was
106+
canceled and both files remained. A second selection of the same exact two
107+
files was then confirmed; only those two named disposable files were
108+
deleted. `/tutorial-capture/hello.py` and its folder were retained.
109+
- On `C81A`, `/tutorial-capture` was created and the Hello PyBLE Blocks starter
110+
was opened in the editable workspace. It was not saved to the board and was
111+
not run.
112+
- On `DA86`, `/examples` was created and
113+
`pyble_hello_console.py` was imported from the public examples repository at
114+
immutable commit `8f4529b3cd0d62e8d53d7deb4f37e5cd2a171fd1`. The imported
115+
file was not opened or run.
116+
- `3DCB` was used only for read-only connection identity.
117+
- The app was left disconnected after the capture session. No other board file
118+
was created, overwritten, or deleted as part of the selected workflow.
119+
120+
## Reviewed capture manifest
121+
122+
The raw and reviewed digests below are copied from the generated
123+
`tutorial-captures.tsv` without abbreviation.
124+
125+
| Stable capture key | Crop | Raw filename | Raw SHA-256 | Reviewed filename | Reviewed SHA-256 |
126+
| --- | --- | --- | --- | --- | --- |
127+
| `setup-five-board-scan` | Full | `07-five-board-scan-stopped.raw.png` | `1d4fbf31f94f80d4d241b321137f316a42dc4770bd62985ec18f4d0b042fc71f` | `pyble-app-0.2.0-build-5-setup-five-board-scan-a89dedab7efc.png` | `a89dedab7efc472332e4280ba145400edf0be2cf2f68acb50d26dca1d2023bcf` |
128+
| `identity-5646-ready` | Ready | `02-connected-5646.raw.png` | `66e63f77decae9a3654a0319b9c194db27c503be43fecbe33c2884fdf12c450e` | `pyble-app-0.2.0-build-5-identity-5646-ready-6b8ef886ea40.png` | `6b8ef886ea4039288e7af1c18921ac41b1b22a10f336a59f96cbf28a74cdb4d2` |
129+
| `identity-5646-chip` | Runtime | `02-connected-5646.raw.png` | `66e63f77decae9a3654a0319b9c194db27c503be43fecbe33c2884fdf12c450e` | `pyble-app-0.2.0-build-5-identity-5646-chip-03edb94bcf73.png` | `03edb94bcf730b72028952962893a3ac26959a3d7c4bf948fbc252757a86e452` |
130+
| `identity-8c9e-ready` | Ready | `03-connected-8c9e.raw.png` | `0af4ea76d1b8af6b920f213ae58d28e1b14bfac2176611927a9d2abad77cbdbc` | `pyble-app-0.2.0-build-5-identity-8c9e-ready-3b64e4b0b84c.png` | `3b64e4b0b84c2d1a81c32b190bfc45d0f294758998bdef1d3c1776d0a1879045` |
131+
| `identity-8c9e-chip` | Runtime | `03-connected-8c9e.raw.png` | `0af4ea76d1b8af6b920f213ae58d28e1b14bfac2176611927a9d2abad77cbdbc` | `pyble-app-0.2.0-build-5-identity-8c9e-chip-0aa751bf86a3.png` | `0aa751bf86a3e7f247a731ecc9ac65b7b2fcb61188201e79c327ba0ca561a3a8` |
132+
| `identity-c81a-ready` | Ready | `04-connected-c81a.raw.png` | `039c2c95dc2cba2a6d6c2848ab6dbf29a782cc519003da54e2561035a19bce01` | `pyble-app-0.2.0-build-5-identity-c81a-ready-8dea0554c432.png` | `8dea0554c432558f5f411a67a2175a5ff762e96c055fd9117ee3fb97906a1fd1` |
133+
| `identity-c81a-chip` | Runtime | `04-connected-c81a.raw.png` | `039c2c95dc2cba2a6d6c2848ab6dbf29a782cc519003da54e2561035a19bce01` | `pyble-app-0.2.0-build-5-identity-c81a-chip-1c4d40085693.png` | `1c4d400856933184a8d37548240469c46850cafc9a76207f17d7b4f9b424c468` |
134+
| `identity-da86-ready` | Ready | `05-connected-da86.raw.png` | `1a086f30edff93085e82326e1605424ab77c2ece69068b8b5f078f01efdcee58` | `pyble-app-0.2.0-build-5-identity-da86-ready-49595991ba1f.png` | `49595991ba1f422ca8e840594b198953d00e3938c1d13d6c9c5e2586d50a0972` |
135+
| `identity-da86-chip` | Runtime | `05-connected-da86.raw.png` | `1a086f30edff93085e82326e1605424ab77c2ece69068b8b5f078f01efdcee58` | `pyble-app-0.2.0-build-5-identity-da86-chip-03edb94bcf73.png` | `03edb94bcf730b72028952962893a3ac26959a3d7c4bf948fbc252757a86e452` |
136+
| `identity-3dcb-ready` | Ready | `06-connected-3dcb.raw.png` | `6e37f11806fc65798670e30c5f49b11d181bb41c7389cc20848384252e8407bf` | `pyble-app-0.2.0-build-5-identity-3dcb-ready-613559d187f3.png` | `613559d187f330e7c7ba3375f86123dbfc4a7ea51b7cb703d34659d9972463e2` |
137+
| `identity-3dcb-chip` | Runtime | `06-connected-3dcb.raw.png` | `6e37f11806fc65798670e30c5f49b11d181bb41c7389cc20848384252e8407bf` | `pyble-app-0.2.0-build-5-identity-3dcb-chip-2b80ef41db8f.png` | `2b80ef41db8f86d5d0d1b79aebf97041fffbba2178817a2a4598ed038c717d96` |
138+
| `first-program-editor-console` | Full | `08-first-program-classic-esp32.raw.png` | `c1e1eb4e6e09605c21e2c79088da290027f8c1ed60cdcf3cd37533d49b872e9c` | `pyble-app-0.2.0-build-5-first-program-editor-console-f6928eea293b.png` | `f6928eea293bd20bcddab94e3e56034033b74a6470cab0f9b018b6a31b969203` |
139+
| `files-multi-delete-review` | Full | `17-files-multi-delete-classic-esp32-idle.raw.png` | `ed3841d421be85009e1019221170d43d6d9e8af61e129d4093d7101a0aa96471` | `pyble-app-0.2.0-build-5-files-multi-delete-review-42cfacddd965.png` | `42cfacddd9657146ba0edfb20273e87e56b5cf8ed9d646c6fd5878f77a728e31` |
140+
| `github-branch-chooser` | Full | `16-github-branch-chooser-generic-s3-clean.raw.png` | `08fbe3108985dc8045d2212c1f6e84ac742bd0709504731979ad809679fb745a` | `pyble-app-0.2.0-build-5-github-branch-chooser-f0c52c24bc5b.png` | `f0c52c24bc5be7412d5e62e2cdbd2708037ed538949c543d121d31aaae5810d7` |
141+
| `github-pinned-source` | Full | `12-github-pinned-source-generic-s3.raw.png` | `a282823b7f1c71d74c6e28b3dc82f9af435c82747ea3fc595769d1179bef3a81` | `pyble-app-0.2.0-build-5-github-pinned-source-68a784c12ada.png` | `68a784c12ada7ae3690e7268cf8b724268ecd81e024c0d92e20ad7870329e372` |
142+
| `github-target-review` | Full | `11-github-target-review-generic-s3.raw.png` | `e13344241f035e46c760abd1ea587d9c70d1e52b218aa6a2ec3c74ed6768c620` | `pyble-app-0.2.0-build-5-github-target-review-16aafa28be77.png` | `16aafa28be77af34696eb61882610a02aa3f8943f5c130de40801b8112b26118` |
143+
| `examples-import-complete` | Full | `14-examples-import-waveshare.raw.png` | `77fa143b86b5267b5c4ccf1e3b101910348279358156b9a0b499fc5628d208dd` | `pyble-app-0.2.0-build-5-examples-import-complete-65fc3f839336.png` | `65fc3f8393366948ee56d183b5ecfdbaf5550a6339e6519c31d0bb6d0ebc8b32` |
144+
| `blocks-hello-workspace` | Full | `13-blocks-hello-c3-idle.raw.png` | `f85a8b92bb5b2567509450b3d7fbeb9ac61935fce27341fe015d11f9e1d17a8a` | `pyble-app-0.2.0-build-5-blocks-hello-workspace-adc069d73fba.png` | `adc069d73fbaab648f2e6b55dc536b38dade609c31aa03f18eb528a634a02f76` |
145+
146+
Technical and privacy review found no account, token, private repository,
147+
notification, personal filename, debug label, integration-test label, or
148+
unrelated board file in the selected derivatives. The public board IDs,
149+
official examples URL, immutable public commit, tutorial source, and named
150+
disposable tutorial files are intentional instructional evidence.

‎docs/testing/tutorial-screenshot-provenance-2026-08-28.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
# Tutorial screenshot provenance — 2026-08-28
44

5+
> **Superseded and corrected:** use the
6+
> [five-board Lenovo capture record](tutorial-five-board-screenshot-provenance-2026-08-28.md)
7+
> for the current tutorial set. A later audit found the Lenovo stylus
8+
> affordance in seven old raw frames (`06` through `12`), not six. This record
9+
> is retained only as historical evidence for the earlier eight-image set.
10+
511
This record covers the physical Android captures prepared for local review of
612
the ten-part learning path. Technical integrity and privacy review are
713
complete. Production publication remains pending explicit user approval of the
@@ -53,7 +59,7 @@ Blocks starter was copied into the editable workspace but was not run.
5359
| Purpose | Raw capture | Published derivative | Reviewed SHA-256 | Privacy and state review |
5460
| --- | --- | --- | --- | --- |
5561
| Setup — board discovery | `06-setup-scan-results-production-release.raw.png` | `pyble-app-0.2.0-build-5-setup-scan-results-3558cadbe501.png` | `3558cadbe501d1865aafbacf4fe5dd9624ae969a2fb0ff7bbd457029bcf2c41c` | Pass; one documentation-board advertisement; Lenovo stylus edge control retained |
56-
| Setup — connected identity | `07-setup-connected-identity-production-release.raw.png` | `pyble-app-0.2.0-build-5-setup-connected-identity-58f65b64a966.png` | `58f65b64a966d4ef2dcd0148442bf07dbe6b2008eda502f9d1e14cda4b7b36ce` | Pass; documentation board only; no unrelated overlay visible |
62+
| Setup — connected identity | `07-setup-connected-identity-production-release.raw.png` | `pyble-app-0.2.0-build-5-setup-connected-identity-58f65b64a966.png` | `58f65b64a966d4ef2dcd0148442bf07dbe6b2008eda502f9d1e14cda4b7b36ce` | Pass; documentation board only; Lenovo stylus edge control retained |
5763
| First program — Editor and Console | `08-first-program-editor-console-production-release.raw.png` | `pyble-app-0.2.0-build-5-first-program-editor-console-86552d68afaa.png` | `86552d68afaa7f9ea8b1151e0ffc812685815f3009bb64b7a3c823090ef42152` | Pass; public tutorial source/output only; Lenovo stylus edge control retained |
5864
| Files — multi-delete review | `09-files-multi-delete-review-production-release.raw.png` | `pyble-app-0.2.0-build-5-files-multi-delete-review-b1df22dfa70a.png` | `b1df22dfa70a449356c05f34189ff897decdfbd418bf4630ae251365b6ed6b86` | Pass; disposable filenames; Delete was canceled; Lenovo stylus edge control retained |
5965
| GitHub — branch chooser | `10-github-import-branch-chooser-production-release.raw.png` | `pyble-app-0.2.0-build-5-github-import-branch-chooser-4514d2f0522b.png` | `4514d2f0522bb3600ba38a75d9ed581255877d1949a8c153341af2d720da8ba7` | Pass; official public URL and public branch only; Lenovo stylus edge control retained |
@@ -63,9 +69,9 @@ Blocks starter was copied into the editable workspace but was not run.
6369

6470
No capture contains an account, token, private repository, notification,
6571
personal filename, debug label, integration-test label, or unrelated user board
66-
file. The small edge control retained in six frames belongs to Lenovo's
72+
file. The small edge control retained in seven frames belongs to Lenovo's
6773
`com.lenovo.styluspen` system package; it contains no user data. It was left
6874
truthful rather than removed by image retouching. The overlay was stopped
6975
reversibly before the final Blocks capture. A future physical recapture may
70-
replace those six frames with new content-versioned assets after the tablet is
76+
replace those seven frames with new content-versioned assets after the tablet is
7177
reconnected; existing published bytes must never be overwritten in place.

0 commit comments

Comments
 (0)