# JOURNEYS.md — MVP-0 Journey Refinement (Dash Rev 3 × V24 Canvas × `hop-local` × O-022)

**Card**: S1 (21 Oct 2026) · **Target Audience**: Low-literacy, Hindi-first outlet crew (WhatsApp-familiar; big tick, few words, one action per screen; ≥48×48 px touch targets) + denser Manager phone screens.  
**Reconciliation Principle**:
- **Functional Truth**: Dash Revision 3 mockups (`dash-mockups/j02*.html`–`j14*.html`, `pilot-patch/*.html`, `docs/JOURNEY-MAP-FABLE-2026-10-10.html`) — authority boundaries, timers, escalation chains, receipts, M3 independent verification, and offline isolation.
- **Visual Truth**: V24 Canvas boards (`project/*.dc.html`) — Hindi-first bilingual labels, embossed warm-blush/teal/gold aesthetic, and the Kiosk (`Ground*`) + Personal Phone (`Phone*`) hardware split.
- **Owner Constitutional Rules (`O-022`, 21 Oct 2026 06:55 IST — Overrides Both Where Contradicted)**:
  1. **PIN reset is the ONLY self-service we offer**: requested from the local kiosk, the request goes to the manager, the manager resets it.
  2. **Two PIN types**: `USER PIN = 4 digits` · `OUTLET KIOSK PIN = 6 digits`.
  3. **Manager PIN-setting lock**: The manager may set/choose a user's PIN **ONLY after that user has asked for a reset** (no manager-initiated PIN changes, so the manager cannot game identity).
  4. **Accountable task selfie mandate**: Every important (accountable / M3 / safety-critical) task carries a **live selfie** (in addition to the 4-digit User PIN).

---

## 0. Upfront O-022 Contradiction Audit (Dash Rev 3 & V24 Boards)

| Rule (`O-022`) | Contradicting Dash Mockup(s) | Contradicting V24 Board(s) | `hop-local` Demo State | Mandatory V25 Resolution |
| :--- | :--- | :--- | :--- | :--- |
| **Rule 1**: PIN reset is the **only** self-service (local kiosk → manager resets it). No self-service SMS/WhatsApp OTP sign-in or phone-based self-recovery. | `pilot-patch/otp-signin.html#patch-screen` shows SMS OTP (explicitly marked **NOT approved** in `pilot-patch/index.html`). `j04-pin-reset-approval.html#reset-help` requires calling the manager by phone first rather than a 1-tap kiosk reset request. | `PhoneOTP.dc.html` (entire board is 4-digit SMS OTP), `Login.dc.html` (`#phone` / `#google` buttons + `"Continue with Phone — 10-digit number, 4-digit OTP"`), `LoginPhone.dc.html` (`ओटीपी भेजें · Send OTP`), `ManagerApprove.dc.html` (`✓ OTP सत्यापित`). | `views.py:render_login_screen` still renders dead `#phone`/`#google` links and disabled `_phone_stub_card`. No PIN reset route exists. | **Retire SMS OTP self-service (`PhoneOTP.dc.html`)**. Replace with Kiosk PIN Reset Request (`पिन रीसेट माँगें · Ask manager to reset PIN`) → Manager open-request reset sheet. |
| **Rule 2**: `USER PIN = 4 digits`; `OUTLET KIOSK PIN = 6 digits`. | `j02-kiosk-signin-approval.html#j02-setup` uses browser-bound approval without a 6-digit Kiosk PIN. `j07-critical-alert-takeover.html#takeover-active` says `Kiosk PIN` for a crew action where it means 4-digit User PIN. | `Login.dc.html`, `Ground.dc.html`, `KioskSelfie.dc.html` show only 4-digit boxes (`••••`) and never distinguish the **6-digit Outlet Kiosk PIN** (device pairing/unlock) from the **4-digit User PIN** (person auth). | `pin_auth.py` & `views.py:_PIN_JS` hardcode 4 digits only; no 6-digit Outlet Kiosk PIN exists. | All crew/manager actions explicitly label **`4-अंकीय यूज़र पिन · 4-digit User PIN` (`••••`)**. Kiosk device pairing/unlock uses **`6-अंकीय कियोस्क पिन · 6-digit Outlet Kiosk PIN` (`••••••`)**. |
| **Rule 3**: Manager may set/choose a user's PIN **only after that user has asked for a reset** (no manager-initiated PIN changes). | `j04-pin-reset-approval.html#reset-first` & `#reset-repeat` have the *worker* choose & repeat their own PIN on the kiosk after a manager grant, rather than the manager resetting/setting it against the open request. | `Manager.dc.html` (line 138) warns `"⚠ PIN already in use — approving asks Ravi for a new PIN on his next tap"` (PIN collision oracle). No board shows the manager setting a 4-digit PIN locked strictly to an open user reset request. | No PIN reset table or route in `store.py` / `main.py`. | Manager can set/choose a user's 4-digit PIN **if and only if** `pin_reset_requests.state == 'OPEN'` (originating from that user on the outlet kiosk). Without an open user request, the manager UI shows `🔒 पिन बदलना बंद है · No open reset request`. |
| **Rule 4**: Every important (accountable) task needs a **selfie**. | `j05b-finish-accountable-task.html#finish-pilot-submit` has no per-action check; `#finish-future-entry` (`Count cash drawer`) asks only for a 4-digit PIN with **no selfie** (`j15` deferred photos). | `GroundTask.dc.html` shows `📷 Take photo` as an optional tile alongside video/voice; `✓ हो गया Done` is active without capturing a mandatory selfie + 4-digit User PIN. | `POST /tasks/{id}/tick` (`main.py:630`) ticks immediately on 1 tap using shared `hop_session` cookie; no selfie or PIN check. | Every accountable / M3 task (`needs_approval`, cash, safety, closing handover) gates `✓ हो गया · Done` behind **live camera selfie + 4-digit User PIN**, stored in DB and shown on Manager M3 verification. |

---

## J1 · Crew Full Day (आगमन से छुट्टी तक · Arrival → Tasks → Readings → Accountable Task → Handover & Checkout)

| Step | Hindi Label + English | Dash Mockup Frame (`file#frame-id`) | V24 Board (`file`) | Demo Route / Template (`hop-local`) | Gap / Risk |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **J1.1** | **कियोस्क पर अपना नाम चुनें** · Arrive at outlet kiosk & tap your name on shift roster | `j02-kiosk-signin-approval.html#j02-start` | `Login.dc.html` (top card), `GroundCheckin.dc.html` | `GET /login` (`views.py:render_login_screen`, `_person_card`) | **P0 1.1 Fixed** (task leaks removed from `/login`). **Open**: `Login.dc.html` & `views.py` still show dead `#phone`/`#google` sign-in stubs violating O-022 Rule 1. |
| **J1.2** | **सेल्फ़ी लें + 4-अंकीय यूज़र पिन डालें** · Same-shift / returning crew: capture live check-in selfie + enter 4-digit User PIN (`••••`) | `j02-kiosk-signin-approval.html#j02-reentry`, `j02b-shift-checkin-out.html#attendance-current` | `KioskSelfie.dc.html`, `Login.dc.html` (middle card) | `GET /login?person={code}`, `POST /login` (`views.py:_person_page`, `_PIN_JS`) | **Critical (`UX-DEEPCHECK 1.2, 6.2`)**: Demo uses `<input type="file" capture="user">` (opens file picker on desktop/kiosk) instead of live `<video>` stream, and **discards the selfie** (`POST /login` only sends `person_id` + `pin`). |
| **J1.3** | **हाज़िरी दर्ज रसीद** · Attendance check-in receipt (`Signed in & checked in · 07:10 · 12h shift window`) + 5s auto-return or switch person | `j02-kiosk-signin-approval.html#j02-collected`, `j02b-shift-checkin-out.html#attendance-current` | `Ground.dc.html` (top check-in banner) | `GET /tasks` (`views.py:_ground_checkin_nudge_html`) | **P0 1.5 Fixed** (banner now binds to `staff['display_name']` and `signed_in_at`). **Open (`1.8, 6.1`)**: Shared kiosk stays logged into one `hop_session` cookie indefinitely; `"This shift"` card has fake `localStorage` 1-tap check-in buttons (`[data-Toggle-Checkin]`). |
| **J1.4** | **अपना फ़ोन अनलॉक — आज के काम** · Personal phone unlocks (`PhoneLocked` → `Phone`) showing shift progress & open tasks above finished tasks | `pilot-patch/tasks-finished-under-open.html#patch-screen`, `j05-my-tasks-big-ticks.html#tasks-open` | `Phone.dc.html`, `PhoneB.dc.html`, `PhoneC.dc.html` | `GET /tasks` (`views.py:render_tasks_screen`, `templates/ground_tasks.html`) | **P0 1.6 Fixed** (hardcoded HTML fallback tasks deleted; DB tasks only + clean empty state). **Open**: Demo serves one layout for both Kiosk and Phone; no finished-tasks-collapsed-under-open-tasks divider on `/tasks`. |
| **J1.5** | **तापमान रीडिंग पहले दर्ज करें (°C)** · Equipment temperature reading surfaced first (`Fridge 2 · °C`), actual numeric entry, **no `Later` button** | `j05-my-tasks-big-ticks.html#tasks-open`, `j08-reading-out-of-range.html#reading-input` | `GroundTask.dc.html` (partial — shows static `4.2°` pill, no keypad) | `GET /tasks/{task_id}` (`views.py:render_task_detail_screen`, `templates/ground_task.html`) | **P0 2.4 Fixed** (fake `4.2 °C` badge replaced with `✓ सिर्फ़ टिक · Tick only`). **Open (`3.4`)**: Neither V24 nor demo has a numeric `°C` keypad/input or min/max threshold check; demo still allows snoozing reading tasks. |
| **J1.6** | **सीमा से बाहर तापमान चेतावनी** · Out-of-range reading (`11 °C > 5 °C`) stored immutably; red/amber warning banner + auto-alert to manager (`Call manager` if routing OFF) | `j08-reading-out-of-range.html#reading-off`, `#reading-unknown`, `#reading-failed`, `j-hindi-draft.html#hi-abnormal-hi` | **NO MOCK** | **NOT BUILT** | **High Risk**: If a chiller is at `11 °C`, crew currently just ticks the task with no numeric value and no out-of-range escalation. |
| **J1.7** | **सामान्य काम — बड़ा टिक (✓ हो गया)** · Routine task completion via single 64px big green tick (`✓ हो गया · Done`) | `j05-my-tasks-big-ticks.html#tasks-open`, `j-hindi-draft.html#hi-routine-hi` | `Phone.dc.html`, `Ground.dc.html`, `GroundTask.dc.html` | `POST /tasks/{task_id}/tick` (`main.py:629`, `store.py:tick_task`) | Works end-to-end in demo. Touch target on `Phone.dc.html` `.t-act` is 36×36 px (needs ≥48×48 px per `UX-DEEPCHECK 4.2`). |
| **J1.8** | **ज़िम्मेदार काम (M3) — सेल्फ़ी + 4-अंकीय पिन अनिवार्य** · Accountable task (`Count cash drawer` / `needs_approval`): requires **live selfie + 4-digit User PIN** (`O-022 Rule 4`) → state becomes `Recorded done; manager check pending` | `j05b-finish-accountable-task.html#finish-pilot-submit`, `#finish-pilot-wait`, `#finish-future-entry`, `j-hindi-draft.html#hi-cash-hi` *(Dash lacks selfie — contradicts O-022 Rule 4)* | `GroundTask.dc.html` *(contradicts O-022 Rule 4: photo optional, no PIN, no `pending manager check` state)* | **NOT BUILT** (`POST /tasks/{id}/tick` marks `COMPLETED` immediately with no selfie, no PIN, and no `PENDING_MANAGER_CHECK` state) | **O-022 P0 Blocker**: Every accountable task must capture a live selfie + 4-digit User PIN and enter `मैनेजर जाँच बाकी · Manager check pending` until an independent manager confirms. |
| **J1.9** | **थोड़ी देर बाद (⌛ +15 मि / +30 मि)** · Defer eligible routine task: 1st tap = `+15 min` (1 of 2); 2nd tap = `+30 min` (2 of 2, requires 1 of 6 reason chips); 3rd tap or `<10 min` to due/handover refused | `j05-my-tasks-big-ticks.html#tasks-later1`, `#tasks-later2`, `#tasks-boundary` | `TaskReason.dc.html` (bottom preview shows `⌛ +30m` pill, no 1-of-2 / 2-of-2 reason sheet) | `POST /tasks/{task_id}/snooze` (`main.py:617`, `store.py:set_item_state`) | **P0 2.5 Fixed** (snooze persists in `hop.item_states`). **Open**: Demo uses arbitrary `<input type="time">` with unlimited snoozes, no reason chip on 2nd snooze, and does not block snoozing on readings/safety/handover boundaries. |
| **J1.10** | **शिफ़्ट हैंडओवर स्वीकार / अस्वीकार** · Shift handover between outgoing & incoming crew/lead: incoming person explicitly taps `Accept eligible item` or `Cannot accept` (distinct from `Read acknowledgement`) | `j09-handover-checkout.html#handover-items`, `#handover-accept`, `#handover-fail` | `Ground.dc.html`, `Phone.dc.html` (shows handover badge `S1→S2` as a plain tick row) | `GET /handovers/{link_id}`, `POST /handovers/{link_id}/tick` (`main.py:609, 668`) | Demo treats a handover identically to a single-person tick (`from_role` or `to_role` can tick with 1 tap; no two-party outgoing/incoming handshake or open-exception carry-over). |
| **J1.11** | **शिफ़्ट छुट्टी (चेक-आउट) + सेल्फ़ी व रसीद** · Shift check-out at kiosk: resolve/hand over open items + live selfie + 4-digit User PIN → `Checked out · 15:05` receipt (preserving open work owner) | `j02b-shift-checkin-out.html#attendance-current`, `#attendance-future`, `j09-handover-checkout.html#handover-items`, `j-hindi-draft.html#hi-checkout-hi` | **NO MOCK** (`Ground.dc.html` only has check-in banner and `Sign out` link) | **NOT BUILT** (`GET/POST /logout` only deletes cookie; no shift check-out timestamp or handover gate in DB) | Crew has no real shift check-out flow, no checkout selfie/PIN verification, and no checkout receipt. |

---

## J2 · First-Time Crew (पहली बार लॉगिन: कियोस्क पेयरिंग → मैनेजर मंज़ूरी → पिन सेटअप → पहली हाज़िरी)

> **O-022 & Dash Reconciliation Note**: V24 framed J2 as `OTP → PIN → first check-in` via `PhoneOTP.dc.html`. However, **SMS OTP sign-in was NOT approved in Dash (`pilot-patch/index.html`, `j03-signin-own-phone.html#signin-a400`)** AND **contradicts O-022 Rule 1** (*"PIN reset is the only self-service we offer: requested from the local kiosk, the request goes to the manager, the manager resets it"*). Below is the reconciled J2 journey preserving V24's visual flow while enforcing O-022 (6-digit Outlet Kiosk PIN + 4-digit User PIN + manager-gated onboarding/PIN setup).

| Step | Hindi Label + English | Dash Mockup Frame (`file#frame-id`) | V24 Board (`file`) | Demo Route / Template (`hop-local`) | Gap / Risk |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **J2.0** | **आउटलेट कियोस्क सेटअप (6-अंकीय कियोस्क पिन)** · Bind/unlock outlet kiosk browser via **6-digit Outlet Kiosk PIN (`••••••`)** + Manager setup approval (`O-022 Rule 2`) | `j02-kiosk-signin-approval.html#j02-setup` *(Dash uses browser grant without 6-digit Kiosk PIN — O-022 Rule 2 adds 6-digit Outlet Kiosk PIN)* | **NO MOCK** (`Login.dc.html` assumes kiosk is already bound) | **NOT BUILT** | **O-022 Rule 2 Gap**: Neither Dash, V24, nor demo implements the **6-digit Outlet Kiosk PIN** (`••••••`) to authenticate the physical outlet kiosk device before crew roster is shown. |
| **J2.1** | **पहली बार आगमन — नाम चुनें या 'मेरा नाम नहीं है'** · First-time crew taps their name on kiosk roster (or taps `मेरा नाम नहीं है · My name is missing` if unrostered) | `j02-kiosk-signin-approval.html#j02-start` | `Login.dc.html` (`+ और लोग दिखाएँ · Show all staff`) | `GET /login`, `GET /login?all=1` (`views.py:render_login_screen`) | V24 `Login.dc.html` and demo have `Show all staff`, but lack Dash's explicit `मेरा नाम सूची में नहीं है · My name is missing` helper card telling unrostered crew to ask their manager. |
| **J2.2** | **मैनेजर से पहली लॉगिन मंज़ूरी माँगें + सेल्फ़ी लें** · Crew captures onboarding live selfie at kiosk & taps `मैनेजर से पूछें · Ask my manager` (replaces unapproved SMS OTP) | `j02-kiosk-signin-approval.html#j02-start`, `j03-signin-own-phone.html#signin-a400`, `pilot-patch/otp-signin.html` *(unapproved)* | `LoginPhone.dc.html`, `PhoneOTP.dc.html` *(**CONTRADICTS O-022 Rule 1 & Dash A400**: uses self-service SMS OTP)* | `GET /login?person={code}` (`mode="ask"`), `POST /login/ask` (`main.py:274`, `approvals.py`) | **Major Contradiction**: V24 `PhoneOTP.dc.html` & `LoginPhone.dc.html` use 10-digit phone + 4-digit SMS OTP. Demo (`POST /login/ask`) follows Dash (`Ask my manager` when `approve_live` is ON) but does not capture an onboarding selfie with the ask. |
| **J2.3** | **प्रतीक्षा स्क्रीन (10 मिनट घड़ी + एस्केलेशन)** · Kiosk shows `मंज़ूरी का इंतज़ार · Waiting for manager` with 10-min countdown & live escalation chain (`Shift Lead now → Cluster Mgr +2m → City/Admin +4m`) | `j02-kiosk-signin-approval.html#j02-wait`, `j-cloud-kitchen.html#cloud-start`, `j-hindi-draft.html#hi-waiting-hi` | `Login.dc.html` (bottom card: `Waiting for Priya · 09:42 left`) | `GET /login?person={code}` (`mode="waiting"`), `GET /login/state`, `POST /login/cancel` (`main.py:259, 308`) | Demo implements the 10m timer and 3s polling (`_WAIT_POLL_JS`), but lacks Dash's visible escalation chain (`Lead 0m → Cluster +2m → City +4m`) and recovery instructions if nobody answers (`#j02-recovery`, `#hi-no_answer-hi`). |
| **J2.4** | **मैनेजर द्वारा पहचान व सेल्फ़ी सत्यापन** · Manager sees request on phone, verifies crew's live kiosk selfie + station, taps `✓ मंज़ूर करें · Approve` (or sets initial 4-digit User PIN if new user ask) | `j02-kiosk-signin-approval.html#j02-lead`, `#j02-manager` | `ManagerApprove.dc.html`, `Manager.dc.html` (inline approval card) | `POST /approvals/{id}/approve`, `POST /approvals/{id}/deny` (`main.py:752`) | **O-022 Contradiction in V24**: `ManagerApprove.dc.html` shows `✓ OTP सत्यापित` badge instead of kiosk request + selfie verification. `Manager.dc.html` shows `"⚠ PIN already in use"` (security leak `UX-DEEPCHECK 6.3`). |
| **J2.5** | **कियोस्क पर मंज़ूरी प्राप्त करें (5 मिनट विंडो) + 4-अंकीय पिन** · Approved banner on kiosk (`5m collect clock: Continue at this Kiosk`); crew enters/confirms their **4-digit User PIN (`••••`)** to complete first check-in | `j02-kiosk-signin-approval.html#j02-approved`, `#j02-collected` | `KioskSelfie.dc.html`, `Login.dc.html` | `GET /login?person={code}` (`mode="pin"`, `approved_by`), `POST /login` (`main.py:320`, `store.py:consume_approval`) | Demo enforces the 5-min collect window (`COLLECT_TTL_SECONDS = 300`) and consumes approval on valid 4-digit PIN! **Gap**: If a brand-new crew member has no PIN yet or requested a PIN setup/reset, demo has no PIN-setting flow (`O-022 Rules 1 & 3`). |
| **J2.6** | **व्यक्तिगत फ़ोन अनलॉक** · Once kiosk check-in succeeds, crew's personal phone transitions from `PhoneLocked` (`पहले कियोस्क पर चेक-इन करें`) to active `Phone` task list | `j03-signin-own-phone.html#signin-result` (Shift gate: `Check in at the outlet Kiosk first`) | `PhoneLocked.dc.html` → `Phone.dc.html` | **NOT BUILT** (Demo has no separate phone session or shift-gated phone lock screen) | `PhoneLocked.dc.html` is a strong V24 board that matches Dash's shift gate (`#signin-result`), but `hop-local` has no route/template for personal phone sign-in or the `PhoneLocked` gate. |

---

## J3 · Manager's Day (मैनेजर का दिन: लाउंज / ज़रूरी कतार → दिन खोलें → मंज़ूरी व पिन रीसेट → M3 काम की जाँच → दिन बंद करें)

| Step | Hindi Label + English | Dash Mockup Frame (`file#frame-id`) | V24 Board (`file`) | Demo Route / Template (`hop-local`) | Gap / Risk |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **J3.1** | **मैनेजर लॉगिन व लाउंज (Lounge)** · Manager signs in on own phone (Google / Email+Password or Manager PIN on kiosk) and lands on Outlet Lounge overview | `j03-signin-own-phone.html#signin-a400`, `pilot-patch/lounge.html#patch-screen` | `Manager.dc.html` | `GET /login` → `POST /login` → redirects manager to `GET /manager` (`main.py:389, 812`) | **Security Bug (`UX-DEEPCHECK 6.4`)**: `GET /manager` does not call `_manager_or_refusal()`; any logged-in crew member (or unauthenticated user!) who visits `/manager` can view the full manager dashboard. |
| **J3.2** | **अभी ध्यान दें (`Needs you now`) — एकल स्नैपशॉट कतार** · Single-snapshot priority queue: Attention badge = `unresolved critical alerts + open unacked tasks`; separate pills for `Access/PIN asks` and `M3 work checks`; noncritical FYI = `0` | `j14-needs-you-queue.html#queue-ready`, `#queue-result`, `#queue-stale`, `#queue-snooze`, `pilot-patch/needs-you-page.html#patch-screen` | `NeedsYou.dc.html`, `Manager.dc.html` (top strip) | `GET /manager` (`views.py:render_manager_screen`) | V24 `NeedsYou.dc.html` mixes login approvals, selfie reviews, and blocked tasks into one `3 pending` counter without Dash's strict formula (`Attention = critical + open tasks`, separate counts for access asks & work checks, stale `3+?` indicator, and 30m local hide with `Bring back`). |
| **J3.3** | **दिन खोलें (`Open Day`)** · Manager opens the outlet business day (`OPEN`), initializing shift sequences | `pilot-patch/lounge.html#patch-screen` | `Manager.dc.html` (`OPEN · Shift 1 of 2`) | `POST /manager/open`, `POST /day/open` (`main.py:884`) | **Security Bug (`UX-DEEPCHECK 6.5`)**: `POST /manager/open` has no `_manager_or_refusal()` check and defaults unauthenticated callers to `staff_id = 5` (Priya). |
| **J3.4** | **लॉगिन मंज़ूरी कार्ड (गैर-अवरोधक / Non-blocking)** · Inline approval card with `✓ Approve`, `✕ Decline`, and `⌛ Later (2 min)` / `✕ Dismiss`; handles multi-manager race (`Already approved by Priya`) | `j02-kiosk-signin-approval.html#j02-lead`, `#j02-manager`, `#j02-denial`, `j14-needs-you-queue.html#queue-result` | `Manager.dc.html`, `ManagerApprove.dc.html`, `NeedsYou.dc.html` | `POST /approvals/{id}/approve`, `POST /approvals/{id}/deny`, `_APPROVAL_LATER_JS` (`views.py:863`) | **P0 1.7 Fixed** (`✕ Dismiss` & `⌛ Later (2 min)` added to inline cards on `/manager`). **Open**: V24 `ManagerApprove.dc.html` lacks `Later (2 min)` button and race-winner receipt state (`Already decided by…`). |
| **J3.5** | **यूज़र पिन रीसेट (केवल खुली कियोस्क रिक्वेस्ट पर — `O-022 Rules 1 & 3`)** · Manager sees an **open kiosk-initiated PIN reset request** from a crew member and sets/resets their **4-digit User PIN (`••••`)**; manager cannot initiate a PIN change without an open user request | `j04-pin-reset-approval.html#reset-wait` *(Dash has manager approve a grant and worker choose PIN on kiosk; O-022 Rule 1 & 3 says request goes to manager, manager resets/sets PIN ONLY after user asks)* | **NO MOCK** (`Manager.dc.html` has no PIN-reset card or open-request lock) | **NOT BUILT** | **O-022 P0 Blocker**: Must build the Manager PIN-Reset sheet that unlocks the 4-digit PIN setter **only** when `pin_reset_requests.state == 'OPEN'` for that user, and shows `🔒 No open reset request from this user` otherwise. |
| **J3.6** | **हाज़िरी सेल्फ़ी मिलान (Confirm / Flag Shift Sign-in)** · Manager compares crew's live check-in selfie against reference photo (`✓ Confirm` or `⚑ Flag mismatch`) | `j02-kiosk-signin-approval.html#j02-manager` (roster + station verification) | `Manager.dc.html` (`Shift sign-ins · tap to verify`), `NeedsYou.dc.html` (`Meena T. · Check-in selfie`) | `GET /manager` (`views.py:render_manager_screen` — static HTML buttons `[data-Shift-Confirm]`, `[data-Shift-Flag]`) | **Fake UI (`UX-DEEPCHECK 2.6`)**: On `/manager`, `✓ Confirm` and `⚑ Flag` only toggle CSS in browser memory (`localStorage`) and vanish on refresh; no backend route or DB column exists. |
| **J3.7** | **ज़िम्मेदार काम (M3) की स्वतंत्र जाँच (सेल्फ़ी + काम का प्रमाण)** · Manager inspects completed accountable/M3 task (`Count cash drawer` / `Sanitise prep table`) with **crew's mandatory selfie (`O-022 Rule 4`)**: taps `✓ Confirm = I checked the work`, `↩ Return for correction`, or `✕ Reject` (no self-confirm; remote manager cannot confirm without local photo/selfie evidence) | `j05b-finish-accountable-task.html#finish-pilot-check`, `#finish-pilot-receipt`, `#finish-future-return`, `j-cloud-kitchen.html#cloud-check`, `j-hindi-draft.html#hi-returned-hi` | `Manager.dc.html` (shows `✓ Confirm` on task rows, but no `Return for correction` / `Reject` or mandatory crew selfie inspection) | **NOT BUILT** (`views.py` `[data-M3-Confirm]` is client-only JS; no backend route, no self-confirm block, no return-for-correction revision loop) | **Critical Functional Gap**: M3 independent verification (`Confirm = I checked the work` vs `Return for correction` with revision history and self-confirmation prohibition) is completely unbuilt in the backend. |
| **J3.8** | **'नहीं हो सका' (`Cannot`) और मरम्मत (`Repair`) की समीक्षा** · Manager sees crew's `Cannot` exception (`Machine broken`) + linked repair request `R-0418` and abnormal temperature alerts in real time | `j06-cannot-exception.html#cannot-manager`, `j08-reading-out-of-range.html#reading-alert`, `j10-repair-payment.html#repair-verify` | `NeedsYou.dc.html` (`Task blocked · Walk-in chiller`), `Manager.dc.html` | **NOT BUILT** (`GET /manager` never queries `hop.item_states`, so crew `BLOCKED`/`SNOOZED` items are invisible to the manager — `REPORT.md` Open Gap) | **P0 Visibility Gap**: Crew can mark a task `✕ Can't do` on `/tasks`, and it persists in `hop.item_states`, but `GET /manager` still shows the task as ordinary `OPEN`! |
| **J3.9** | **दिन बंद करें (`Close Day`) — प्री-फ़्लाइट जाँच + 4-अंकीय मैनेजर पिन** · Manager reviews pre-close summary (open tasks, unverified M3 items, unresolved handovers/exceptions), enters **4-digit User PIN**, and closes the day (`CLOSED` immutable snapshot) | `j02b-shift-checkin-out.html#attendance-exception`, `j09-handover-checkout.html#handover-items` | `Manager.dc.html` (`CLOSE DAY — ALL 18 VERIFIED` button) | `POST /manager/close`, `POST /day/close` (`main.py:913`, `store.py:close_day`) | **Security & UX Bug (`UX-DEEPCHECK 3.2, 6.5`)**: `POST /manager/close` allows closing the day when 0/12 tasks are ticked with no warning modal, and falls back to `closer_id = 5` without requiring a manager session or PIN. |

---

## J4 · Something Goes Wrong (गड़बड़ी व अपवाद: गलत पिन ×3 → कियोस्क पिन रीसेट · फ़ोन गुम · काम नहीं हो सकता · मरम्मत · गंभीर अलर्ट · ऑफ़लाइन)

| Step | Hindi Label + English | Dash Mockup Frame (`file#frame-id`) | V24 Board (`file`) | Demo Route / Template (`hop-local`) | Gap / Risk |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **J4.1** | **गलत पिन ×3 → कियोस्क से पिन रीसेट माँगें (`O-022 Rule 1`)** · Crew enters wrong 4-digit User PIN 3 times (or taps `पिन भूल गए? · Forgot PIN?`) on the local kiosk → taps `मैनेजर से पिन रीसेट माँगें · Request PIN Reset` (the **only** self-service flow) | `j04-pin-reset-approval.html#reset-help`, `j-hindi-draft.html#hi-reset-hi`, `#hi-mismatch-hi` *(Dash requires calling manager; O-022 Rule 1 makes kiosk-to-manager reset request our sole self-service)* | `Login.dc.html` (`PIN reset? Ask manager` text hint — not interactive) | `POST /login` returns 401 `That PIN didn't match. Try again.` (`main.py:364`); **no ×3 counter and no PIN reset request route** | **O-022 P0 Blocker**: After 3 wrong PINs (or tapping `पिन भूल गए?`), kiosk must show a big primary CTA: `🔑 पिन रीसेट माँगें · Ask Manager to Reset PIN`, creating an `OPEN` reset request for that user while preserving their open task context. |
| **J4.2** | **मैनेजर द्वारा पिन रीसेट (`O-022 Rules 1 & 3`) → काम पर वापसी** · Manager opens the user's active reset request on `/manager`, sets/resets the user's **4-digit User PIN (`••••`)**, and crew signs in at kiosk to resume their open task | `j04-pin-reset-approval.html#reset-wait`, `#reset-first`, `#reset-repeat`, `#reset-error`, `#reset-success` *(Amended by O-022 Rule 3: manager sets/resets PIN only against open user request)* | **NO MOCK** | **NOT BUILT** | **O-022 P0 Blocker**: Needs both the Manager open-request PIN setter card and the Kiosk reset-complete receipt (`पिन बदल दिया गया · PIN reset complete — continue to your task`). |
| **J4.3** | **फ़ोन खो गया / बैटरी ख़त्म — साझा कियोस्क मोड (`Recording as…`)** · Crew without personal phone uses the shared outlet kiosk: persistent header shows `अभी लॉगिन: रवि · Recording as Ravi` + 1-tap `व्यक्ति बदलें · Change person` + 60s inactivity auto-lock | `j02b-shift-checkin-out.html#attendance-future`, `j05-my-tasks-big-ticks.html#tasks-open` | `Ground.dc.html`, `GroundTask.dc.html` | `GET /tasks`, `GET /tasks/{id}` (`views.py:render_tasks_screen`, `render_task_detail_screen`) | **Identity Collision Risk (`UX-DEEPCHECK 1.8`)**: Demo sets a persistent `hop_session` cookie with no auto-timeout, and `Ground.dc.html` / `/tasks` uses tiny `Sign out` text instead of Dash's high-contrast `Recording as Ravi · [Change person]` bar. |
| **J4.4** | **काम नहीं हो सकता (`✕ नहीं हो सकता · Cannot`) — 6 कारण चिप्स + आवाज़** · Crew taps `✕ Cannot`, selects 1 of 6 structured reasons (`No stock`, `Machine broken`, `Short staff`, `Manager said`, `Not my shift`, `Other + voice note`) and submits | `j06-cannot-exception.html#cannot-reasons`, `#cannot-failed` | `TaskReason.dc.html` | `POST /tasks/{id}/cant-do`, `POST /handovers/{id}/cant-do` (`main.py:613, 621`, `templates/ground_task.html`) | **P0 2.5 Fixed** (`BLOCKED` state persists in DB). **Open**: Demo uses a plain text input instead of the 6 structured Hindi/English reason chips in `TaskReason.dc.html` / Dash `j06`, and voice note (`🎤`) is a dead stub. |
| **J4.5** | **'नहीं हो सका' रसीद + ऑटो-लिंक्ड मरम्मत (`R-0418`)** · Selecting `Machine broken` records immutable `Cannot` receipt AND auto-creates linked repair ticket `R-0418` (or shows `Repair report not sent · Retry sending repair` if secondary call fails) | `j06-cannot-exception.html#cannot-saved`, `#cannot-repair`, `j-hindi-draft.html#hi-cannot_saved-hi` | **NO MOCK** (`TaskReason.dc.html` jumps straight to `RepairNew.dc.html` without showing the partial-failure/linked receipt state) | **NOT BUILT** | Dash explicitly requires separating the task exception write (`Recorded: could not do`) from the repair creation write so a network hiccup doesn't lose the crew's task exception. |
| **J4.6** | **नई मरम्मत रिपोर्ट (`🔧 न्यू रिपेयर`) + हिंदी→अंग्रेज़ी अनुवाद** · Crew picks broken equipment chip, speaks/types Hindi description (`दरवाज़ा बंद नहीं हो रहा`), sees live English translation preview for manager/vendor, attaches photo, and gets routed/unrouted receipt `R-0418` (`City Head authorises → Independent manager verifies → 2-step payment`) | `j10-repair-payment.html#repair-report`, `#repair-authorise`, `#repair-verify`, `#payment-city`, `#payment-business`, `#payment-finance`, `pilot-patch/maintenance-ground.html`, `pilot-patch/maintenance-approval-flow.html` | `RepairNew.dc.html` (has equipment chips, Hindi note + EN translation preview, photo box; lacks `R-0418` receipt & authority chain) | **NOT BUILT** (`views.py:559` has a dead `<a href="#repair">` link on `/tasks`) | `RepairNew.dc.html` is visually excellent for crew intake, but needs a submit receipt state (`R-0418`) and backend route (`GET/POST /repairs`), plus manager verification on `/manager`. |
| **J4.7** | **गंभीर सुरक्षा अलर्ट टेकओवर (`Critical Alert Takeover`)** · Urgent safety hazard (`Gas smell near oven` / `Fridge 2 critical`) takes over screen: requires **4-digit User PIN + live selfie (`O-022 Rule 4`)** to mark `Done`, allows `Snooze 5 min` (max 2 times, showing `1 of 2` / `2 of 2 used`), or `Call manager` | `j07-critical-alert-takeover.html#takeover-active`, `#takeover-snoozed`, `#takeover-max`, `#critical-pinned` | `Ground.dc.html` (shows inline red alert banner `गैस की गंध — ओवन के पास · ✓ Fixed / Call Priyank`, not a modal takeover with 2-snooze cap) | `views.py:521-529` (hardcoded static HTML banner on `/tasks` with client-only `localStorage` dismiss `[data-Resolve-Alert]`) | **Safety Risk**: Critical alert on `/tasks` is hardcoded fake HTML that disappears into `localStorage` with 1 tap — no 4-digit User PIN, no selfie (`O-022 Rule 4`), no 5-min snooze cap (max 2), and no server persistence. |
| **J4.8** | **ऑफ़लाइन काम व चेक-आउट कतार (`Offline Queue & Reconcile`)** · When Wi-Fi/4G drops: tasks & readings save into an **actor-isolated local queue** (`Captured for Ravi — waiting for signal`; preserved if Meena switches onto the kiosk); offline checkout records local timestamp and reconciles on reconnect | `j-offline-failure.html#offline-task`, `#offline-checkout`, `#offline-reconcile`, `j-hindi-draft.html#hi-offline-hi` | `Main.dc.html` (shows tiny `Offline-ready · 12 queued` pill in overview, no actual board state) | **NOT BUILT** | If outlet internet drops during peak shift, form `POST`s fail with browser network error; no `IndexedDB`/localStorage actor-isolated outbox or offline banner exists. |

---

## (a) `NO MOCK` Steps → New V25 Boards to Create

The following 6 steps exist in Dash Revision 3 and/or are mandated by **Owner Rules (`O-022`)**, but have **no V24 `.dc.html` board** today (full 5-line specs are in `V25-BOARD-DELTAS.md` Part 2):

1. **`KioskSetup6Pin.dc.html` (J2.0 — O-022 Rule 2 + Dash `j02#j02-setup`)**: First-time / renewal outlet kiosk binding screen requiring the **6-digit Outlet Kiosk PIN (`••••••`)** + manager setup approval receipt before unlocking the outlet roster.
2. **`KioskPinReset.dc.html` (J4.1, J4.2 — O-022 Rule 1 + Dash `j04#reset-help`, `#reset-success`)**: Kiosk self-service PIN reset flow triggered after 3 wrong 4-digit User PIN attempts (or tapping `पिन भूल गए?`): sends an `OPEN` reset request to the manager, shows waiting status, and displays the reset-complete receipt to resume the crew member's open task.
3. **`ManagerPinReset.dc.html` (J3.5, J4.2 — O-022 Rules 1 & 3 + Dash `j04#reset-wait`)**: Manager phone sheet for resetting/choosing a crew member's **4-digit User PIN (`••••`)**, strictly gated by an active, user-initiated kiosk reset request (`OPEN` request state vs. `🔒 Locked — user has not requested a reset`).
4. **`GroundReading.dc.html` (J1.5, J1.6 — Dash `j05#tasks-open`, `j08#reading-input`, `#reading-off`)**: Dedicated equipment temperature reading board (`Fridge 2 · °C`) with large numeric keypad (`-`, `0–9`, `.`), **no `Later` button**, and instant out-of-range warning state (`11 °C > 5 °C` → auto-alert to manager + `📞 Call manager`).
5. **`GroundCheckout.dc.html` (J1.10, J1.11 — Dash `j02b#attendance-future`, `j09#handover-items`, `#handover-accept`)**: Shift handover & check-out board showing unresolved items/readings to hand over, incoming crew acceptance (`Accept` vs `Cannot accept`), live checkout selfie + 4-digit User PIN (`••••`), and immutable checkout receipt (`Checked out · 15:05`).
6. **`CriticalTakeover.dc.html` (J4.7, J4.8 — Dash `j07#takeover-active`, `#takeover-max`, `j-offline-failure#offline-task` + O-022 Rule 4)**: Full-screen critical safety alert takeover (`Gas smell near oven` — requires live selfie + 4-digit User PIN to mark `Done`, `Snooze 5 min` [1 of 2 / 2 of 2 max], `Call manager`) plus actor-isolated offline queue banner (`Waiting for signal · 2 items saved for Ravi`).

---

## (b) `NOT BUILT` Steps in `hop-local` Ranked by MVP-0 Importance

| Rank | Step(s) | Feature / Capability | Why It Is MVP-0 Critical |
| :---: | :--- | :--- | :--- |
| **1 (P0 — O-022)** | **J1.2, J1.8, J2.2, J3.6, J3.7** | **Live Camera Selfie Capture + Server Storage + Accountable Task Selfie & 4-Digit PIN Gate (`O-022 Rule 4`)** | Currently `<input type="file">` opens a file dialog and `POST /login` throws the image away (`UX-DEEPCHECK 1.2, 6.2`), while `POST /tasks/{id}/tick` ticks accountable tasks in 1 tap with no selfie and no 4-digit User PIN. Violates O-022 Rule 4. |
| **2 (P0 — O-022)** | **J3.5, J4.1, J4.2** | **Kiosk Self-Service PIN Reset Request → Manager Open-Request PIN Setter (`O-022 Rules 1 & 3`)** | Currently there is zero recovery when a crew member forgets their 4-digit PIN (`UX-DEEPCHECK 2.2`). Must implement `POST /login/pin-reset-ask` (kiosk) and `POST /manager/pin-reset/{id}` (manager sets new 4-digit PIN **only** when an open user request exists). |
| **3 (P0 — O-022)** | **J2.0** | **6-Digit Outlet Kiosk PIN (`••••••`) vs. 4-Digit User PIN (`••••`) (`O-022 Rule 2`)** | Outlet kiosk mode must be unlocked/bound with a **6-digit Outlet Kiosk PIN** (`••••••`), keeping all individual staff/manager PINs strictly **4 digits** (`••••`). |
| **4 (P0 — Auth/Sec)** | **J3.1, J3.3, J3.8, J3.9** | **Manager Route Protection (`_manager_or_refusal`), `item_states` Visibility on `/manager`, & Pre-Close Gate** | `/manager`, `/manager/open`, and `/manager/close` lack `_manager_or_refusal()` (`staff_id = 5` fallback); `/manager` ignores `hop.item_states` (so crew `BLOCKED`/`SNOOZED` tasks look `OPEN` to the manager); `/manager/close` closes with 0/12 tasks ticked. |
| **5 (P0 — Core Ops)** | **J3.7, J1.8** | **M3 Independent Manager Verification (`PENDING_MANAGER_CHECK` → `Confirm` / `Return for correction`)** | Accountable tasks (`needs_approval`) must wait in `Recorded done; manager check pending` until an independent manager inspects the crew's selfie/proof and confirms (blocking self-confirmation) or returns for correction (`Revision 2`). |
| **6 (P1 — Core Ops)** | **J1.5, J1.6** | **Numeric Temperature Reading Input (`°C`) + Out-of-Range Alert + No-Snooze Rule** | Cold-chain/oven tasks (`Fridge 2 · °C`) need a real numeric `°C` field stored in DB, automatic out-of-range detection (`11 °C > 5 °C`), and snooze disabled. |
| **7 (P1 — Shared Kiosk)** | **J1.3, J4.3** | **`Recording as {Name}` Banner + 1-Tap `Change Person` + 60s Kiosk Auto-Timeout** | On a shared outlet kiosk, leaving `hop_session` active indefinitely causes the next worker to accidentally tick tasks under the previous worker's identity (`UX-DEEPCHECK 1.8`). |
| **8 (P1 — Exceptions)** | **J1.9, J4.4, J4.5, J4.6** | **Structured 6-Reason `Cannot` Chips, Snooze Cap (`+15m` / `+30m` max 2), & Repair Intake (`R-0418`)** | Replace free-text `reason` and arbitrary `<input type="time">` with Dash's 6 reason chips, 2-snooze cap, and `Machine broken` → linked repair ticket (`R-0418`) with Hindi→English translation. |
| **9 (P1 — Attendance)** | **J1.10, J1.11, J2.6** | **Real Shift Check-In/Out DB Ledger, Two-Party Handover Acceptance, & `PhoneLocked` Shift Gate** | Replace fake `localStorage` shift buttons (`UX-DEEPCHECK 6.1`) with server-persisted shift check-in/out receipts, incoming handover acceptance, and personal phone shift-gating. |
| **10 (P2 — Resilience)** | **J4.7, J4.8** | **Server-Backed Critical Alert Takeover (Max 2 Snoozes) & Actor-Isolated Offline Queue** | Replace hardcoded `localStorage` gas alert on `/tasks` with a real takeover modal (selfie + 4-digit PIN to resolve, max 2 × 5m snoozes) and an offline `IndexedDB` outbox isolated per `staff_id`. |

---

## (c) Disagreements Between Dash Rev 3, V24 Canvas, and Owner Rules (`O-022`) — With Recommendations

| # | Topic | Dash Revision 3 Position | V24 Canvas Position | Owner Rules (`O-022`) | Recommendation for V25 & MVP-0 |
| :---: | :--- | :--- | :--- | :--- | :--- |
| **1** | **Phone OTP Sign-In / Self-Service Recovery** | **Rejected**: `pilot-patch/index.html` & `j03#signin-a400` explicitly mark SMS/WhatsApp OTP as **NOT approved**; crew uses Kiosk (`Ask my manager`) or Google/Email on own phone. | **Prominent**: `PhoneOTP.dc.html`, `LoginPhone.dc.html`, `Login.dc.html`, and `ManagerApprove.dc.html` center on 10-digit mobile + 4-digit SMS OTP (`✓ OTP सत्यापित`). | **Rule 1**: *"PIN reset is the only self-service we offer: requested from the local kiosk, the request goes to the manager, the manager resets it."* | **Follow O-022 + Dash**: Retire `PhoneOTP.dc.html` and remove SMS OTP from `Login.dc.html`, `LoginPhone.dc.html`, and `ManagerApprove.dc.html`. Kiosk PIN Reset Request → Manager is the sole self-service flow. |
| **2** | **Who Chooses the New 4-Digit User PIN on Reset?** | In `j04-pin-reset-approval.html#reset-first` & `#reset-repeat`, the manager approves a recovery grant on their phone, and the **worker** types & repeats a new 4-digit PIN on the kiosk. | `Login.dc.html` says `"PIN reset? Ask manager"` with no screen for either manager or worker. `Manager.dc.html` leaks `"⚠ PIN already in use"`. | **Rules 1 & 3**: *"requested from the local kiosk, the request goes to the manager, the manager resets it."* AND *"The manager may set/choose a user's PIN ONLY after that user has asked for a reset (no manager-initiated PIN changes, so the manager cannot game identity)."* | **Follow O-022 Literally**: Worker requests PIN reset at the local kiosk (`KioskPinReset.dc.html`). That creates an open request on the manager's phone (`ManagerPinReset.dc.html`), unlocking the 4-digit PIN setter for that specific user. Remove the `"PIN already in use"` collision warning (`UX-DEEPCHECK 6.3`). |
| **3** | **PIN Lengths (User vs. Outlet Kiosk)** | Uses 4-digit PIN for staff re-entry (`j02#j02-reentry`) and browser-bound manager approval for Kiosk setup (`j02#j02-setup`); labels crew PIN as `Kiosk PIN` in `j07#takeover-active`. | Uses 4-digit PIN (`••••`) everywhere (`Login.dc.html`, `KioskSelfie.dc.html`); no 6-digit Outlet Kiosk PIN exists. | **Rule 2**: *"USER PIN = 4 digits; OUTLET KIOSK PIN = 6 digits."* | **Follow O-022 Rule 2**: Standardize labels across all boards: **`4-अंकीय यूज़र पिन · 4-digit User PIN` (`••••`)** for every person, and **`6-अंकीय कियोस्क पिन · 6-digit Outlet Kiosk PIN` (`••••••`)** on `KioskSetup6Pin.dc.html` to unlock/pair the outlet kiosk. |
| **4** | **Selfie on Accountable / M3 Tasks** | `j05b#finish-pilot-submit` has no per-action check; `#finish-future-entry` (`Count cash drawer`) requires **4-digit PIN only** (photos deferred in `j15` A331). | `GroundTask.dc.html` makes `📷 Take photo` an optional tile and lets crew tap `✓ हो गया Done` with neither selfie nor PIN. | **Rule 4**: *"Every important (accountable) task needs a selfie."* | **Follow O-022 Rule 4 + Dash M3 State**: Every accountable / M3 task (`needs_approval`, cash drawer, food-safety sanitizer/reading override, closing handover) requires **live selfie + 4-digit User PIN** before transitioning to Dash's `Recorded done; manager check pending` (`#finish-pilot-wait`). |
| **5** | **`Needs You Now` Queue Counting Formula** | `j14-needs-you-queue.html#queue-ready`: Top Attention count = `unresolved critical alerts + open unacked tasks ONLY`. Access asks and M3 work checks have **separate** sub-counters; noncritical FYI = `0`. | `NeedsYou.dc.html`: Combines login approval (1) + check-in selfie verification (1) + blocked task (1) into a single `3 pending` badge. | Silent (defers to functional truth). | **Adopt Dash's Formula inside V24's Card Layout**: Keep `NeedsYou.dc.html`'s clean Hindi-first cards, but split the header into **Attention Count** (`Critical + Open Tasks`) and **Action Pills** (`🔑 Access/PIN Asks` · `✓ M3 Work Checks`) so routine sign-in asks never mask a critical chiller failure. |
| **6** | **Snooze (`Later`) Rules & Temperature Readings** | `j05#tasks-open` & `j08#reading-input`: **No `Later` button** on temperature readings or critical safety items. Routine tasks get max 2 snoozes: 1st = `+15 min`, 2nd = `+30 min` + mandatory reason chip; 3rd refused. | `Phone.dc.html`, `Ground.dc.html`, `GroundTask.dc.html`: Show `⌛ बाद में · Later` on **every** task (including chiller temperature check!) and `TaskReason.dc.html` shows `+30m` without tracking 1-of-2 vs. 2-of-2. | Silent (defers to functional truth). | **Adopt Dash's Snooze Guardrails in V25**: Hide `⌛ बाद में · Later` on all temperature reading, safety-critical, and accountable closing tasks; enforce `1st = +15 min (free)` and `2nd = +30 min (with reason chip, final)` on routine tasks. |

---

## (d) Owner Questions (Max 5 — Each With Recommended Default)

1. **PIN Delivery After Manager Sets/Resets a 4-Digit User PIN (`O-022 Rules 1 & 3`)**: When a crew member requests a PIN reset from the kiosk and the manager sets/chooses their new 4-digit User PIN on `ManagerPinReset.dc.html`, how does the crew member learn the new 4-digit digits?
   - **Recommended Default**: **In-person / voice relay + Kiosk verification** — The manager tells the crew member the 4 digits in person (or by phone call if remote cluster manager), and the kiosk screen (`KioskPinReset.dc.html`) immediately prompts the crew member to type those 4 digits (`••••`) + take a selfie to confirm receipt and unlock their task. *(Never display the plaintext PIN unattended on the public kiosk screen.)*
2. **When Is the 6-Digit Outlet Kiosk PIN (`O-022 Rule 2`) Prompted?**: Should the 6-digit Outlet Kiosk PIN (`••••••`) be required only once when pairing/booting the kiosk browser (and after an explicit kiosk sign-out/reset), or every morning when opening the day?
   - **Recommended Default**: **On device pairing / browser session boot + after any kiosk lock/reset** (stored in an `HttpOnly` kiosk-binding token for 30 days, with a 1-tap `🔒 Lock Kiosk` button for the manager). Daily crew interactions on the unlocked kiosk only ever ask for the crew member's **4-digit User PIN (`••••`)**.
3. **Which Tasks Count as "Important (Accountable)" for Mandatory Selfie (`O-022 Rule 4`)?**: Should **every** task in the shift sequence require a selfie, or only tasks flagged `accountable / needs_approval` (M3 tasks, cash drawer, critical alerts, equipment readings, and shift handovers), leaving routine cleaning ticks (`Wipe display glass`) as 1-tap big ticks (`✓`)?
   - **Recommended Default**: **Gate all `accountable` (`needs_approval` / M3), cash, critical-alert resolution, and shift handover/check-in/out actions behind mandatory live selfie + 4-digit User PIN**, while keeping routine cleaning/prep tasks (`Wipe counter`, `Restock napkins`) as fast 1-tap big green ticks (`✓`) so crew aren't taking 40 selfies a shift.
4. **Personal Phone Sign-In for Crew Without Corporate Google/Email (`J2.6` / Dash `A400`)**: Since SMS OTP is unapproved and `O-022 Rule 1` restricts self-service to Kiosk PIN reset, how should a crew member bind their **personal phone** (`LoginPhone.dc.html`)?
   - **Recommended Default**: **Kiosk-Paired QR / 4-Digit User PIN after Kiosk Check-In** — Crew checks in at the outlet kiosk first (selfie + 4-digit User PIN), then signs in on their personal phone using their Staff Selection + **4-digit User PIN** (active only while checked into an open shift at the outlet, otherwise showing `PhoneLocked.dc.html`).
5. **Shared Kiosk Session Timeout (`J1.3, J4.3`)**: When a crew member signs in on the shared outlet kiosk to tick tasks, how quickly should the kiosk auto-revert from `Recording as Ravi` back to the outlet roster (`/login`)?
   - **Recommended Default**: **60 seconds of inactivity** (with a visible countdown pill in the top bar and an instant 1-tap `⇄ व्यक्ति बदलें · Change person` button), plus immediate lock after completing a check-in or checkout receipt (5 seconds).
