anthodev/lapin-futepublic Fork
⑂ develop
Commits
⬇ Clone ▾
git clone https://git.rickub.com/anthodev/lapin-fute.git
git clone ssh://git@rickub.com/anthodev/lapin-fute.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

[feature] Deliver Pebble watch consultation #7

Closed@github-anthodev opened this issue Aug 29, 2026
  • @github-anthodev opened this issue · Aug 29, 2026

    🔢 Impact Version (SemVer)

    MINOR


    🌿 Suggested Branch

    feature/watch-consultation/watch/7


    📝 Description

    Deliver the primary interaction: browse favorites and consult departures with an event-only request policy. Implement the five watch states, app-open/settled-selection/manual-refresh triggers, phone-cache-first rendering, atomic results, bilingual copy, compact AppMessage use, and battery-conscious platform rendering.


    ✅ Expected Behavior

    Opening the watch app displays the last complete active-favorite result immediately when available, then allows one cache-governed refresh. Up/Down changes favorites and only the final selection after 500 ms can request; Select is the explicit refresh gesture. No timer/background path performs network I/O, and fresh 60-second phone cache suppresses upstream work.


    📋 Acceptance Criteria

    • Implement exactly UNCONFIGURED, LOADING, READY, STALE, UNAVAILABLE; missing key/no favorites maps to UNCONFIGURED with a direct bilingual instruction to open companion options and configure a key/favorite; invalid/revoked key maps to actionable UNAVAILABLE.
    • On app open with keyStatus=CONFIGURED, request the active favorite only after showing cached data; serve without backend/PRIM activity when cache age is under 60 seconds. MISSING/INVALID makes zero XHR.
    • Up/Down browse stored order immediately, but debounce the network trigger until selection is unchanged for 500 ms; intermediate scroll positions make zero XHR.
    • Select explicitly refreshes only the active favorite. Fresh cache may answer it; suppress duplicate in-flight requests and never immediately retry a failure.
    • Back keeps normal platform behavior. App close cancels pending debounce/ticks and, because PebbleKit JS stops, leaves no background work.
    • Render the per-platform departure limit — three rows on emery, two rows on gabbro — with screen.round-aware responsive layout, nextIntervalMinutes, delayed/cancelled state, source freshness, and refresh time from the foundation contract.
    • Keep the prior complete result visible during refresh; apply only one complete matching replacement. Do not resend AppMessage when normalized visible content and freshness are unchanged.
    • Use minute ticks only while the app is active and only to update age/countdown; ticks must never trigger XHR/AppMessage. Use no second ticks, steady-state animations, vibration, or forced backlight.
    • Build the UI in Piu with built-in system fonts only: touchCount 0 (button-only input), no font/media assets, no animations, and no touch polling.
    • Localize authored copy in French/English (fr → French, otherwise English); keep user/backend labels verbatim.
    • Both emulators (emery and gabbro) render all states and representative long French/English copy without clipping critical information, honoring screen.round on the round display.
    • Across a scripted 50-refresh/rapid-navigation run, remain within foundation heap/message budgets with zero dropped/failed AppMessages and no growth after steady state.
    • A live result atomically replaces a recorded result; install/configure/consult one favorite on the named Pebble Time 2 (emery) physical watch.
    • Record state/locale captures on emery and gabbro, per-event XHR/AppMessage counts, cache-hit and debounce proof, 50-refresh XS/heap/message evidence, live replacement, and Pebble Time 2 physical proof in a resolution comment.

    🔗 Affected Endpoints/Routes

    • No backend route is added.
    • Consume the departure result/error route from [feature] Normalize live PRIM departures (https://github.com/Anthodev/lapin-fute/issues/4) through PebbleKit JS and the AppMessage protocol from [feature] Establish the application foundation and contracts (https://github.com/Anthodev/lapin-fute/issues/2).

    🧪 Tests to Add

    Type Coverage
    Alloy model/protocol/Piu tests Five states, key-status mapping, navigation/debounce, cache-first/loading transitions, duplicate suppression, minute-tick no-I/O, atomic display
    PebbleKit JS integration tests App-open/settled-selection/Select triggers only, 60-second cache, no immediate retry, unchanged-result AppMessage suppression
    Localization/emulator tests Complete French/English resources, fallback/verbatim labels, every state and long label on both emery and gabbro (round layout included)
    Runtime smoke 50 refreshes with XS/heap/message counters; app close zero activity; stored config → live result; Pebble Time 2 physical watch

    ⚙️ Constraints

    • The watch never searches, types, contacts external APIs, receives/stores the key, or owns a scheduler.
    • The five states are exhaustive; a late/mismatched result never renders.
    • App open, final favorite selection after 500 ms, and Select are the only request triggers; every trigger is cache-governed and app exit cancels outstanding UI scheduling.
    • Fit the frozen platform/Alloy-runtime budgets (binary, loaded image/RAM, XS arenas, AppMessage) rather than dropping a target or enlarging AppMessage buffers speculatively.
    • No background execution of any kind — periodic/background polling, Wakeup, Worker, timeline subscriptions — and no animations, vibration, touch input/polling, or backlight changes remain in scope; the Alloy app declares no background capability.

    🔀 Dependencies

    • Blocked by [feature] Normalize live PRIM departures (https://github.com/Anthodev/lapin-fute/issues/4).
    • Blocked by [feature] Persist and synchronize favorites (https://github.com/Anthodev/lapin-fute/issues/6).
    • Reuse the platform matrix, physical watch, shared contracts, localization resources, and AppMessage protocol from [feature] Establish the application foundation and contracts (https://github.com/Anthodev/lapin-fute/issues/2).

    ⚠️ Impact on Existing Behavior

    Replaces the recorded fixture display from [feature] Establish the application foundation and contracts (https://github.com/Anthodev/lapin-fute/issues/2) with the complete consultation runtime and makes the configuration committed by [feature] Persist and synchronize favorites (https://github.com/Anthodev/lapin-fute/issues/6) user-visible.


    🔍 Technical Context

    Default layout intent:

    Do not hard-code this English wording; use the frozen bilingual resource strategy and adapt layout to emery (three rows) and gabbro (two rows), honoring screen.round.

    Required references

Sign in to comment.