Place Journey v2 — S14 · Events + Alerts (the megaphone layer)

The LAST civic screen — when the village needs to speak to everyone at once. Implements S14-decision-sheet.md verbatim (✅ designed; 🚫/⏳ absent; 🔨/⚠️ in captions/foot). A1: ONE unified broadcast CARD LANGUAGE — event / official broadcast / channel / alert are all the REAL post card (DECISIONS #11, refs/real-place-feed-post.png) with a wrapper-level left-border urgency accent (S6-C9 pattern): red alert · amber official · teal event · neutral channel — one Flutter widget, variant props, never a redesigned card. A2: placement differs by class — events in feed date-sorted, broadcasts/channels labeled in feed, alerts = PINNED banner above the header + 🚫 NO browsable alert feed (a scroll of past alarms trains catastrophizing). A3: the reader never sees the taxonomy — only WHO + HOW-URGENT. Trust governs alerts: class gates + corroboration + honesty labels + mandatory retraction push; 🔴 E14 kill-switch (per-alert kill + Region.alertsFrozen + CMS dashboard) ships BEFORE any alert UI. Resolves the S8-B8 channels-in-feed, S13-D9 broadcast-in-feed and S6 D15 share-card deferrals. Depends on S13 verifiedCivic live.

‹ All screensS14·A Megaphone feedS14·B EventsS14·C Alert classesS14·D Lifecycle + safetyS14·E D15 share + stripS14·F hi locale
S14 · megaphone feed · unified card language

Four broadcast classes, ONE card — accents do the talking

Implements A1 — all four broadcast-class cards are the REAL post card (DECISIONS #11: .s6-post anatomy 1:1 from refs/real-place-feed-post.png) + a WRAPPER-level left-border accent (S6-C9): teal EVENT ("Gram Sabha · Tomorrow 11am · Panchayat Bhawan", जाऊंगा + "12 going" social proof B5), amber OFFICIAL (seat display name "MLA · Marhaura" + verified badge, S13-D9 unlocked), neutral CHANNEL (Bheldi Mandi Bhav, S8-B8 unlocked), and a NORMAL post for contrast — one Flutter widget, variant props, 🚫 never a new card. A2 the active alert is a PINNED dismissible red banner ABOVE the header (G17 — too urgent for the personal strip slot); 🚫 no browsable alert feed — only the 7-day collapsed "recent alerts" audit row at feed bottom. A3 the reader never sees the class taxonomy — only WHO + HOW-URGENT; 🚫 tabs per class (2G tap cost). Feed order = A1's ONE query: upcoming events (<7d, date-sorted) → recent broadcasts → normal recency. 🔨 getPlaceBroadcastFeed = ONE query (active alerts by severity → events by startDateTime → broadcasts), not three · channel posts need the NEW Post.groupId sparse field (separate pre-build decision; circleId wall stands per S8-B7) · alert = Post w/ NEW ALERT source.provider + denormalized {class,severity,verified,killAt} + AlertOverlay collection (C9).

3:42
••••
No power in Bheldi since 2 pm
Reported by residents — not officially confirmed · Active 1h ago

Bheldi Village

Home · Resident
BheldiVillage6 GarkhaBlockquiet SaranDistrict140 BiharState2.1k
6new
Feed →
3open
Issues →
1event
Gram Sabha →
Overview
Feed6
Issues3
Communities
People
EventTomorrow 11am · Panchayat Bhawan12 going
SD
Sunita Devi@sunita_bheldi
Bheldi, Bihar · 3hSarpanch
Gram Sabha — road repair budget discussion. Everyone is invited.
9 4 184
OfficialFrom the office of MLA · Marhaura
MLA · Marhaura
Marhaura constituency · 5h
Marhaura–Garkha road tender is approved. Work starts next month — schedule will be posted here.
31 12 640
ChannelBheldi Mandi Bhav · daily rates
MB
Bheldi Mandi Bhav58 members
Bheldi, Bihar · 7h
Today's rates: wheat ₹2,150 · paddy ₹1,890 per quintal at Garkha mandi.
MS
Manoj Singh@manoj_bheldi
Bheldi, Bihar · yesterdayResident
Chhath ghat cleaning drive this Sunday morning — bring gloves, tea is on me.
Recent alerts — last 7 days2 · view ›
S14 · events · feed, pull-list, detail

Events — the feed IS the calendar

Implements B4 first-class event type — EVENT POST_TYPE already exists; 🔨 extend PostEvent: endDateTime + recurrence{freq,until} (weekly haat / monthly gram sabha materialize the NEXT occurrence — the "हर सोमवार haat" row) + rsvpCount; regionIds REQUIRED on civic events (today they inherit silently); 🚫 calendar view v1 — no village persona uses one, feed-of-upcoming IS the calendar at ~3 events/month · A2 feed placement is PRIMARY (date-sorted, <7d, above normal posts), the pull-list is the SECONDARY migrant surface — "what's happening at home next month" · B5 the 5-second detail sheet: KAB (relative date — today/tomorrow/N-days, never ISO) · KAHAN (landmark name, never coords) · KYA/KAUN (what's expected + WHO called it — sarpanch vs BDO changes attendance, role chip); RSVP verb renders per locale (hi जाऊंगा / नहीं जाऊंगा shown as the canonical label — 🚫 the word "RSVP" never renders; en key "I'll go"); RSVP = reminder CONSENT → T-24h + T-1h SmartNotif (server-cron, not client timers), de-RSVP cancels; याद दिलाएं = reminder without commitment; count = social proof · B6 OPEN creation + role chip (official/steward events badged, steward can PIN one); recurring official events fan out via S13 VCM. 🔨 EventRsvp = NEW collection — 🚫 reuse PostLike (attend ≠ like, different Gorse signal). Metric: event view→share ≥20% on home-place events (share = understood + valued; RSVP is vanity here).

3:42
••••
Events — in Bheldi3
Pull-list = the migrant surface (A2). Feed stays primary; this list is reachable from the Today strip's event cell + the ⋯ menu.
Kal11 am
Gram Sabha — road budget
Panchayat Bhawan · by Sarpanch
Pinned 12 going
Monhaat
Weekly haat
Every Monday · school ground
Sat9 am
Teeka camp — children under 5
PHC Garkha · by ASHA
7 going
B4: the haat row is the recurrence model — freq=weekly materializes only the NEXT occurrence, never a wall of repeats. Date chip = relative (Kal/Mon/Sat), B5's KAB rule. Steward pin = ONE event max (B6).
Event detail — the 5-second sheet (B5)
Gram SabhaEvent
Kab
Tomorrow, 11 amThursday 12 June
Kahan
Panchayat Bhawannear the middle school
Kya · Kaun
Road repair budget — bring your ward's demands. Called by Sunita DeviSarpanch
12 going · Ramesh, Anita and 10 others
B5: जाऊंगा = reminder consent — T-24h + T-1h SmartNotif ride the N1 pipeline; tapping again (नहीं जाऊंगा) cancels both. याद दिलाएं = reminder-only, no public count. 🔨 EventRsvp collection writes here, NOT PostLike.
Create — open to everyone (B6)
Add an event for Bheldi
B6: open creation; official/steward events carry the role badge (the WHO is the trust signal, A3). hi vocabulary: कार्यक्रम / मेला / सभा — 🚫 the raw word "Event" on the hi locale.
S14 · alerts · class + corroboration

Five classes, one banned — corroboration before the siren

Implements C7 the CLASS GATE — who may raise + TTL per class; Class-E (communal / "suspicious person" / violence) is ABSENT BY DESIGN — BANNED v1 ⚠️: not gated, not configurable, does not EXIST in the picker (the WhatsApp-rumor-to-mob vector — a simultaneous push inverts speed into amplified violence; DM/SP use S13 broadcast for genuine law-order); 🚫 free-text/"Other" subtype (a Class-E proxy) · C8 CORROBORATION (utility class only): raiser → PENDING (visible to raiser + stewards ONLY, no wide push) → "Is this true in your area?" SmartNotif to the 50 most-recently-active residents → 3 unique confirms (distinct, ≥7d accounts, in-VCM, not raiser/followers) → LIVE + push; 45-min window else silent expire; 🔨 AlertCorroboration NEW collection (🚫 PostLike — Gorse corruption + honesty break) · C9 alert = Post (🔨 NEW ALERT source.provider + denormalized {class,severity,verified,killAt}) + 🔨 AlertOverlay (corroborationCount, verificationState, regionScope, killAt/By, notifBatchId) — mirrors issue=post; NAMED always, 🚫 anonymous (village social accountability is the false-alert brake) · C10 honesty labels verbatim — 🚫 EVER labeling a resident alert "Verified"; staleness decay "Active 2h ago — may no longer be current" · missing person = POLICE-OFFICIAL only + FIR ref ⚠️, photo → NSFW pipeline · 🔨 D12 FULL alert text IN the push payload (offline-render — "you have an alert" + 8s feed load costs lives), NEW CIVIC_ALERTS Android channel priority:10, iOS time_sensitive wired, critical/DND-break needs the Apple entitlement ⚠️ owner action; emergency severity BYPASSES N1 bundling + preference checks ⚠️.

3:42
••••
Raise an alert — what happened?C7
Emergency — flood, fire, evacuation
Officials only
48h
Weather warning
Officials or weather office
12h
Health — outbreak, PHC notice
Officials or ASHA worker
24h
Power · water · road
Any resident — needs 3 neighbour confirmations
6h
Missing person
Police officials only · FIR number required
72h
C7: five classes, NOTHING else — no "Other", no free text. The sixth class isn't hidden — it doesn't exist (⚠️ Class-E ban, owner-veto window; lead strongly recommends holding). Reader never sees this taxonomy (A3) — only WHO + HOW-URGENT.
1 · Pending corroboration — raiser + stewards only (C8)
AlertPower · Bheldi · raised by Ramesh Kumar
No power in Bheldi since 2 pm — transformer near the school is sparking.
Unverified — awaiting neighbour confirmation · 1 of 3
Only you and place stewards can see this
Power cut reported near you — is this true in your area?
Asked to 50 recently-active Bheldi residents · 3 confirmations make it live · expires silently in 45 min
C8: confirms must be distinct ≥7-day accounts, in-VCM, not the raiser or their followers. 🔨 AlertCorroboration collection. 🚫 ZERO Seva for raising or corroborating (E15 — gamification = attack surface).
2 · Live — resident alert, honest label (C10)
AlertPower · Bheldi
No power in Bheldi since 2 pm — transformer near the school is sparking.
Reported by residents — NOT officially confirmed · 3 reported
Active 2h ago — may no longer be current
3 · Official emergency (C7 · C10)
EmergencyFlood · Garkha Block
Gandak embankment overflow expected tonight. Move cattle and grain to higher ground. Relief camp: Garkha high school.
From the office of District Magistrate, Saran
4 · Missing person — police + FIR (C7 ⚠️)
MissingBheldi + Garkha Block
Ravi Kumar, 9, last seen near Bheldi haat Tuesday evening. Blue shirt, school bag.
From Marhaura Police Station
FIR 214/26 · call 112 with any information
⚠️ Missing-person = police-only + FIR ref (owner-veto window) — photo runs the NSFW pipeline before publish. TTL 72h → collapsed audit, no second push.
S14 · alerts · lifecycle + safety rails

Retract loudly, resolve honestly, kill instantly

Implements C11 RETRACTION: raiser self-retract <60 min (utility class); steward anytime WITH a reason chip; official/admin for official classes; every retraction fires a MANDATORY "corrected" push to the original recipients — silence after a flood warning is ambiguous; 🔨 OneSignal collapse_id on the original so the retraction collapses the unread alert (Android); 🚫 auto-retract via flag count — 3 flags = review + "Under review" label, never auto-kill (a coordinated group could silence a real emergency, S13-C8) · resolved state + F16 "tell neighbours Bheldi is safe" D15 share = the ONLY alert-as-acquisition path — 🚫 auto-share or reshare button on a LIVE/unverified alert (don't platform-amplify possible falsehood; 🚫 alert reshare button at all, E15) · H18 ONE-DIRECTIONAL alert→issue: "File as a civic issue →" pre-fills the S7 composer (category + body, rides S6-D14 placeId wiring) — urgent panic becomes a durable civic record; an issue never becomes an alert · 🔴 E14 BUILD BEFORE ANY ALERT UI ⚠️ (app can't depict admin — this caption is the carrier): (a) per-alert kill → KILLED + retraction push <2 min (b) Region.alertsFrozen sparse boolean — place-level freeze kills pending+live and blocks new = the mob-situation switch, one field + one check (c) class-level feature flags (d) CMS dashboard of all live alerts. Alerts CANNOT ship without (a)+(b)+(d). E15 graduated penalty ⚠️: utility cap 2/place/7d; 2 retractions/30d → RAISE_CIVIC_ALERT cooldown 60d; 3+ → admin review. 🔨 TTL lazy-expire + SOFT_DELETE cron.

3:42
••••
Lifecycle — four statesC11 · F16 · H18 · E14
1 · Retract — reason chip, then the mandatory correction (C11)
Withdraw this alert?
It's fixed now I was wrong Posted by mistake
N
✅ Correction — power is back in Bheldi
The earlier power-cut alert has been withdrawn by the reporter.
Sent to everyone who got the original alert · collapses the unread original (collapse_id)
C11: the corrected push is NOT optional — every original recipient gets it. 🔨 collapse_id replaces the unread alert on Android; 🚫 flag-count auto-kill (3 flags = "Under review" label + steward review only).
2 · Resolved — the only alert share (F16)
ResolvedPower · Bheldi · was live 4h
No power in Bheldi since 2 pm — transformer near the school is sparking.
No longer active — resolved 30 min ago
Tell neighbours Bheldi is safeShare →
F16: the resolved-safe card is the ONLY alert share — 🚫 share affordance on live/unverified alerts (screenshots are uncontrollable, but never facilitated). Opens the S14·E D15 card pre-filled.
3 · Alert → issue, one direction (H18)
AlertWater · Bheldi · live
Hand-pump water coming out muddy across the east tola since morning.
File as a civic issue
H18: pre-fills the S7 composer (category=water + body) — the 6h alert dies, the issue lives until fixed. Alerts never appear in the Issues tab; an issue can never spawn an alert.
4 · Frozen — the kill-switch, user side (E14 🔴)
Alerts are paused in Bheldi for now
Region.alertsFrozen=true renders exactly this: raise entry disabled, pending + live alerts killed, no drama, no explanation that could inflame. The admin side (per-alert kill, class flags, CMS live-alert dashboard) is build-first and CANNOT be depicted in-app — 🔴 it ships BEFORE any of this screen.
S14 · D15 share + Today-strip arbitration

The WhatsApp-status card — honest, or absent

Implements F16 — the D15 share/invite card, finally designed (resolves the S2/S3/S6 deferrals): 9:16 WhatsApp-status format, CLIENT-rendered off the already-loaded landing payload (S10-C8 pattern, zero server cost, theme-independent export); place name + HONEST count (the SAME 7-day figure as the Today strip — Law #7) + next-event OR open-issues line; all-zero → the card is SUPPRESSED — no ghost-town card ever leaves the app. Fires from exactly three triggers: quiet-feed CTA (S6-E17 / S3-C10b destination) · post-RSVP "invite to {event}" · resolved-alert "Bheldi is safe" (S14·D); 🚫 auto-share of any live/unverified alert. The S10 user-achievement card stays a DISTINCT artifact. G17 arbitrates the S3 cell-③ conflict: an active alert is NEVER a strip cell — it's the dismissible banner ABOVE the header (too urgent for the personal slot); cell ③ priority ladder = RSVP'd-event-within-24h → upcoming-event-count (7d) → Seva delta → completeness. 🔨 nextEvent + activeAlert optional fields on GetPlaceLandingResponse (one query each, ride the 10-min cache BUT invalidatePlaceDetail on every alert write — and the client double-gates killAt<now against a stale cache). Metric: weekly alert/event engagement (RSVP ∪ alert-tap ∪ D15-share ÷ visitors) ≥25% in 90d; place_share_card_sent{trigger}.

3:42
••••
D15 — the 9:16 status cardF16
Nyburs
Bheldi
Garkha · Saran · Bihar
23 neighbours were active this week
Gram Sabha — tomorrow 11 am, Panchayat Bhawan
See your village on Nyburs
F16: count = the strip's own 7d figure, never inflated (Law #7). The event line falls back to "3 issues being tracked" when no event is upcoming; ALL-ZERO → no card, the share entry simply doesn't render. Client-side render → WhatsApp status; theme-independent export.
Cell ③ priority ladder (G17)
1Gram Sabha · kal 11am जाऊंगा ✓RSVP'd event <24h
22 events this weekupcoming count (7d)
3★ +15 Seva this weekSeva delta
462% built · Finishcompleteness
G17: first non-empty state wins the ③ slot. 🔨 nextEvent + activeAlert ride GetPlaceLandingResponse; alert writes bust the 10-min cache (invalidatePlaceDetail) + client double-gates killAt<now.
Alert placement — banner, never a cell (G17)
No power in Bheldi since 2 pm
Sits ABOVE the place header · dismissible · re-pins on new alert
An active alert outranks every personal state — but it gets its OWN surface (the pinned banner of S14·A), so the personal ③ slot never loses its job. Dismiss is per-alert; a NEW alert re-pins.
S14 · hi locale reference — translation check (NOT a design pattern)

The megaphone feed, rendered in the hi locale

DECISIONS #8: ONE language per screen via i18n — this frame renders S14·A end-to-end in hi. Vocabulary locked by the sheet's i18n block: alert banner = चेतावनी (disaster) vs सूचना (info); event tag = कार्यक्रम (मेला/सभा per type); official = घोषणा; channel = चैनल; RSVP = जाऊंगा / नहीं जाऊंगा, reminder = याद दिलाएं — 🚫 raw "Alert" / "Event" / "RSVP" / "Broadcast" anywhere on the hi locale. Honesty labels translate fully: "निवासियों की सूचना — आधिकारिक पुष्टि नहीं", staleness "2 घंटे पहले — अभी भी हो ज़रूरी नहीं", official "ज़िलाधिकारी कार्यालय की ओर से". Going-count = "12 जा रहे हैं". Numerals, ₹ rates, handles and the brand "Nyburs" stay Latin. Layout, components, accents and ordering identical to S14·A. 🔨 full hi i18n batch ships WITH the screen (alert push payload text is also localized — the push IS the alert on 2G, D12).

3:42
••••
चेतावनी — भेल्दी में 2 बजे से बिजली नहीं है
निवासियों की सूचना — आधिकारिक पुष्टि नहीं · 1 घंटे पहले

भेल्दी गाँव

घर · निवासी
भेल्दीगाँव6 गढ़खाप्रखंडशांत सारणज़िला140 बिहारराज्य2.1k
6नई
फ़ीड →
3खुली
समस्याएँ →
1सभा
ग्राम सभा →
ओवरव्यू
फ़ीड6
समस्याएँ3
समुदाय
लोग
कार्यक्रमकल 11 बजे · पंचायत भवन12 जा रहे हैं
सु
सुनीता देवी@sunita_bheldi
भेल्दी, बिहार · 3 घंसरपंच
ग्राम सभा — सड़क मरम्मत बजट पर चर्चा। सब ज़रूर आएँ।
9 4 184
घोषणाविधायक कार्यालय · मरहौरा की ओर से
विधायक · मरहौरा
मरहौरा क्षेत्र · 5 घं
मरहौरा–गढ़खा सड़क का टेंडर पास हो गया है। काम अगले महीने शुरू होगा — समय-सारणी यहीं मिलेगी।
31 12 640
चैनलभेल्दी मंडी भाव · रोज़ के भाव
मं
भेल्दी मंडी भाव58 सदस्य
भेल्दी, बिहार · 7 घं
आज का भाव: गेहूँ ₹2,150 · धान ₹1,890 प्रति क्विंटल (गढ़खा मंडी)।
मनोज सिंह@manoj_bheldi
भेल्दी, बिहार · कलनिवासी
रविवार सुबह छठ घाट की सफ़ाई — दस्ताने लेकर आएँ, चाय मेरी तरफ़ से।
पिछले 7 दिन की चेतावनियाँ2 · देखें ›

Journey position: S14 closes the civic journey (S1 entry → … → S13 authority → S14 megaphone). The feed/banner frames render inline on the place page (Feed tab, Place branch root); composer/picker/detail surfaces are pushed sheets. One language per screen (DECISIONS #7/#8): en frames + the S14·F hi check. Build ledger (S14 = mostly net-new, sequenced): 🔴 FIRST — per-alert kill + Region.alertsFrozen + class feature-flags + CMS live-alert dashboard (E14; alerts CANNOT ship without a+b+d; depends on S13 verifiedCivic production-ready) · AlertOverlay + AlertCorroboration NEW collections (C8/C9, 🚫 PostLike reuse) · NEW ALERT source.provider + denormalized {class,severity,verified,killAt} marker · PostEvent extend endDateTime/recurrence/rsvpCount + EventRsvp NEW collection (B4/B6) · getPlaceBroadcastFeed ONE unified query (A1) · Post.groupId sparse field for channel posts (A3 — separate pre-build decision; the S8-B7 circleId wall stands) · CIVIC_ALERTS Android channel priority:10 + FULL alert text in the push payload (offline render, D12) + iOS time_sensitive (wired) + Apple critical-push entitlement (⚠️ owner action) + emergency-severity preference/bundling BYPASS (⚠️) · TTL lazy-expire + SOFT_DELETE cron · nextEvent/activeAlert on GetPlaceLandingResponse + invalidatePlaceDetail on alert write + client killAt double-gate (G17) · mutateAlertScope (regionIds ancestor-chain expansion, D13) + delta push + multi-region cache invalidation · OneSignal collapse_id retraction (C11) · D15 client-rendered share card (F16) · alert→issue composer pre-fill rides S6-D14 placeId wiring (H18) · LadderAlert app stub → real · full hi i18n batch. ⚠️ Owner-veto window (design-frozen until vetoed/confirmed): Class-E communal/suspicious-person ban (C7 — lead strongly recommends hold) · missing-person police-only + FIR (C7) · Apple critical-push entitlement (D12, owner action) · emergency-severity preference-bypass (D12) · utility cap 2/place/7d + retraction cooldowns (E15) · alertsFrozen/kill-switch-first (E14 — strongly recommend hold). Metrics: event view→share ≥20% (home-place) · weekly alert/event engagement ≥25% in 90d · alert→issue conversion ≥10% · events: place_event_rsvp/created/share · alerts: place_alert_raised{class,role}/corroborated/label_seen/resolved/false_flagged/converted_to_issue · place_share_card_sent{trigger}.