Watchapp distribution: UUID, appinfo, versioning and install path (#70) #109

Merged
robert merged 1 commit from tooling/watchapp-distribution into main 2026-09-05 12:04:10 +02:00
Owner

Closes #70.

What this does

UUID. watchapp/package.json's pebble.uuid (834379e0-d559-497d-8082-d02546fec8d1) already
existed from the original scaffold (#75/D54) — verified as a genuine pebble-tool-generated RFC 4122
v4 UUID (version nibble 4, variant nibble 8), not a hand-typed placeholder. Nothing was
regenerated.
It is recorded here as the app's permanent identity: once this merges, it must never
change.

appinfo, checked against the installed SDK, not recalled docs. Diffed a real pebble build's
generated build/appinfo.json against package.json and against this SDK's own bundled schema
(sdk-core/pebble/common/tools/schemas/). package.json now has a real author, an explicit
capabilities: [] (nothing calls health_service_* yet — grepped — so this is correct today, with a
note in docs/DEV.md to add "health" the moment real HRM code lands), and a menuIcon.
targetPlatforms keeps emery, gabbro and basalt (basalt stays as a build/emulator-only
regression target, cheap since it's the same 64-colour codebase — CI already builds/screenshots it).
One gap found and flagged rather than silently worked around: the bundled schema's targetPlatforms
enum doesn't list gabbro at all — checked, and it's the schema file lagging the SDK; a real
pebble build with gabbro compiles and links fine (re-run as part of this PR).

Icon — placeholder, stated honestly. watchapp/resources/images/icon.png: a plain 25×25 PNG
(black wheel rim + spokes, one PP_COLOR_ACCENT_BLUE hub dot from palette.h, transparent
background), one menuIcon used on both emery and gabbro. 25×25 is this SDK's actual enforced
ceiling — read from the installed toolchain's own process_sdk_resources.py
(max_menu_icon_dimensions=(25,25), a real bld.fatal check), not recalled from old CloudPebble
docs. This is not finished branding — it exists so the app has a legible icon instead of none,
pending real design input from Robert.

Versioning — two numbers, on purpose. PROTO_CONTRACT_VERSION (PROTOCOL.md §6) and the
watchapp/companion release version are independent: most releases bump the release version without
touching the protocol contract at all. The release version is an ordinary semver string, kept
identical in watchapp/package.json's version (→ versionLabel in the generated appinfo — only the
major.minor half survives on-device, per generate_appinfo.py) and companion/build.gradle.kts's
versionName, both 0.1.0 right now. versionCode is Android's own separate integer, bumped by 1
per release, uninvolved in the watch/phone pairing check. Full scheme + release checklist:
docs/DEV.md#releasing.

Distribution — decided: Forgejo releases, not a store. Not Rebble, not Core Devices — the rolling
dev-latest pre-release (every push, dev-artifact.yml) and a real vX.Y.Z release per tag
(tag-lane.yml) were already built and merged tonight (D63); this PR documents that as the actual
decision the issue asked for, rather than inventing a new channel. No account, no review queue, and
the repo is already public with anonymous release-asset download.

Install instructions + the #53 handshake, named. README.md gets an "Installing" section covering
both halves and stating plainly that an update to only one half is caught by the PROTO_VERSION
handshake (#53) refusing to start a ride on mismatch, rather than run with plausible wrong numbers.

One CI bug found and fixed, not left broken. tag-lane.yml's G11 identity gate grepped
package.json for a literal "versionLabel" key. That field only ever exists in the generated
build/appinfo.json — never in package.json itself (confirmed via the schema diff above) — so the
check always silently found nothing and never actually fired. Fixed to grep the real field,
version. This touches a file outside #70's own "Files" list, but leaving a known-dead release gate
in place while writing the versioning scheme it's supposed to check felt worse than a one-line,
narrowly-scoped correction — flagged here for visibility.

docs/DECISIONS.md gets a new entry, D64, with every checked fact above (D48 requires new
entries be grounded in checked facts, not arguments — this one is entirely SDK-source/schema/CI
reads, no new argument).

Verified for real

  • pebble build — clean, all three of emery/gabbro/basalt link and bundle, including the new
    icon resource compiling through resource_ball/inject-metadata without the 25×25 dimension check
    failing.
  • ./gradlew :companion:assembleDebug — clean, produces companion-debug.apk.

Files touched

  • watchapp/package.json, watchapp/resources/images/icon.png (new)
  • companion/build.gradle.kts (comment only — versionCode/versionName values unchanged, already
    aligned at 1 / "0.1.0")
  • docs/DEV.md (new "Releasing" section), docs/PROTOCOL.md §6, docs/DECISIONS.md (D64),
    README.md
  • .forgejo/workflows/tag-lane.yml (G11 field-name fix)
Closes #70. ## What this does **UUID.** `watchapp/package.json`'s `pebble.uuid` (`834379e0-d559-497d-8082-d02546fec8d1`) already existed from the original scaffold (#75/D54) — verified as a genuine `pebble-tool`-generated RFC 4122 v4 UUID (version nibble `4`, variant nibble `8`), not a hand-typed placeholder. **Nothing was regenerated.** It is recorded here as the app's permanent identity: once this merges, it must never change. **appinfo, checked against the installed SDK, not recalled docs.** Diffed a real `pebble build`'s generated `build/appinfo.json` against `package.json` and against this SDK's own bundled schema (`sdk-core/pebble/common/tools/schemas/`). `package.json` now has a real `author`, an explicit `capabilities: []` (nothing calls `health_service_*` yet — grepped — so this is correct today, with a note in docs/DEV.md to add `"health"` the moment real HRM code lands), and a `menuIcon`. `targetPlatforms` keeps `emery`, `gabbro` and `basalt` (basalt stays as a build/emulator-only regression target, cheap since it's the same 64-colour codebase — CI already builds/screenshots it). One gap found and flagged rather than silently worked around: the bundled schema's `targetPlatforms` enum doesn't list `gabbro` at all — checked, and it's the schema file lagging the SDK; a real `pebble build` with `gabbro` compiles and links fine (re-run as part of this PR). **Icon — placeholder, stated honestly.** `watchapp/resources/images/icon.png`: a plain 25×25 PNG (black wheel rim + spokes, one `PP_COLOR_ACCENT_BLUE` hub dot from `palette.h`, transparent background), one `menuIcon` used on both `emery` and `gabbro`. 25×25 is this SDK's actual enforced ceiling — read from the installed toolchain's own `process_sdk_resources.py` (`max_menu_icon_dimensions=(25,25)`, a real `bld.fatal` check), not recalled from old CloudPebble docs. **This is not finished branding** — it exists so the app has *a* legible icon instead of none, pending real design input from Robert. **Versioning — two numbers, on purpose.** `PROTO_CONTRACT_VERSION` (PROTOCOL.md §6) and the watchapp/companion *release* version are independent: most releases bump the release version without touching the protocol contract at all. The release version is an ordinary semver string, kept identical in `watchapp/package.json`'s `version` (→ `versionLabel` in the generated appinfo — only the major.minor half survives on-device, per `generate_appinfo.py`) and `companion/build.gradle.kts`'s `versionName`, both `0.1.0` right now. `versionCode` is Android's own separate integer, bumped by 1 per release, uninvolved in the watch/phone pairing check. Full scheme + release checklist: `docs/DEV.md#releasing`. **Distribution — decided: Forgejo releases, not a store.** Not Rebble, not Core Devices — the rolling `dev-latest` pre-release (every push, `dev-artifact.yml`) and a real `vX.Y.Z` release per tag (`tag-lane.yml`) were already built and merged tonight (D63); this PR documents that as the actual decision the issue asked for, rather than inventing a new channel. No account, no review queue, and the repo is already public with anonymous release-asset download. **Install instructions + the #53 handshake, named.** README.md gets an "Installing" section covering both halves and stating plainly that an update to only one half is caught by the `PROTO_VERSION` handshake (#53) refusing to start a ride on mismatch, rather than run with plausible wrong numbers. **One CI bug found and fixed, not left broken.** `tag-lane.yml`'s G11 identity gate grepped `package.json` for a literal `"versionLabel"` key. That field only ever exists in the *generated* `build/appinfo.json` — never in `package.json` itself (confirmed via the schema diff above) — so the check always silently found nothing and never actually fired. Fixed to grep the real field, `version`. This touches a file outside #70's own "Files" list, but leaving a known-dead release gate in place while writing the versioning scheme it's supposed to check felt worse than a one-line, narrowly-scoped correction — flagged here for visibility. `docs/DECISIONS.md` gets a new entry, **D64**, with every checked fact above (D48 requires new entries be grounded in checked facts, not arguments — this one is entirely SDK-source/schema/CI reads, no new argument). ## Verified for real - `pebble build` — clean, all three of `emery`/`gabbro`/`basalt` link and bundle, including the new icon resource compiling through `resource_ball`/`inject-metadata` without the 25×25 dimension check failing. - `./gradlew :companion:assembleDebug` — clean, produces `companion-debug.apk`. ## Files touched - `watchapp/package.json`, `watchapp/resources/images/icon.png` (new) - `companion/build.gradle.kts` (comment only — versionCode/versionName values unchanged, already aligned at 1 / "0.1.0") - `docs/DEV.md` (new "Releasing" section), `docs/PROTOCOL.md` §6, `docs/DECISIONS.md` (D64), `README.md` - `.forgejo/workflows/tag-lane.yml` (G11 field-name fix)
Watchapp distribution: UUID, appinfo, versioning and install path (#70)
Some checks failed
dev-artifact / build-pbw (push) Failing after 0s
dev-artifact / build-apk (push) Failing after 0s
dev-artifact / publish (push) Has been skipped
fast-lane / host-c-tests (push) Failing after 0s
fast-lane / jvm-tests (push) Failing after 0s
fast-lane / pebble-build (push) Failing after 0s
fast-lane / lint-and-secrets (push) Failing after 0s
fast-lane / meta-declares-required-jobs (push) Failing after 0s
fast-lane / host-c-tests (pull_request) Failing after 0s
fast-lane / jvm-tests (pull_request) Failing after 0s
fast-lane / pebble-build (pull_request) Failing after 0s
fast-lane / lint-and-secrets (pull_request) Failing after 0s
fast-lane / meta-declares-required-jobs (pull_request) Failing after 0s
b233cde2a8
Confirms the watchapp UUID (834379e0-…, a genuine pebble-tool-generated
RFC 4122 v4 UUID from the original scaffold, not a placeholder) as
permanent, completes watchapp/package.json's appinfo (author, capabilities,
a real menuIcon, targetPlatforms for emery/gabbro/basalt — verified against
the installed pebble-tool 5.x / SDK 4.33.1 schema and waf source, not
recalled docs), defines a watchapp/companion release-version scheme that is
explicitly independent of PROTO_CONTRACT_VERSION, aligns companion
versionName to it, documents the Forgejo-releases distribution mechanism
already built by dev-artifact.yml/tag-lane.yml, and fixes tag-lane.yml's
G11 gate, which was grepping package.json for a field name that only ever
exists in the generated appinfo.json.

- watchapp/package.json: real author/capabilities/menuIcon; version 0.1.0
- watchapp/resources/images/icon.png: placeholder 25x25 menu icon (wheel,
  palette.h's accent blue hub) — explicitly not final branding
- companion/build.gradle.kts: comment tying versionName to the new scheme
- docs/DEV.md: new "Releasing" section — UUID permanence, appinfo field
  mapping (checked against the SDK), versioning scheme, distribution
  decision, install instructions, release checklist
- docs/PROTOCOL.md §6: app version vs PROTO_VERSION, explicitly not the
  same number
- docs/DECISIONS.md: D64, the checked facts behind all of the above
- README.md: Installing section naming the #53 protocol-mismatch handshake
- .forgejo/workflows/tag-lane.yml: G11 field-name fix + versioning-scheme
  comment update

Verified for real: `pebble build` (emery/gabbro/basalt, all three link and
bundle with the new icon resource) and `./gradlew :companion:assembleDebug`
both succeed on this change.

Claude-Session: https://claude.ai/code/session_01DAoXbRmJUf2uxNYBfdAXPt
robert merged commit aa2fe7870c into main 2026-09-05 12:04:09 +02:00
Sign in to join this conversation.
No description provided.