The patrol surface behind publish-then-patrol. Implements S11-decision-sheet.md verbatim (✅ designed; 🚫/⏳ absent; 🔨 in captions/foot). The desk is a PUSHED page — simple app bar, never the place header. Core moves: B5 OLD→NEW diff on every queue item (the steward's #1 gap — correction vs vandalism), B6 priority-tier ordering ①report ②claimed-official/MCC ③phone ④new-account, B7 trust signals = account age + accepted-count (🚫 Seva score on cards), B8 desk diet (no ladder, halved banner, pending badge on the entry tile), C10 canned reject chips with needs-a-source as the social escape hatch, C12 the one-sentence patrol briefing, D13 🔴 rollback writes its own revision, D15 action-framed reverts. 🔴 B9: flag-as-incorrect is a silent server no-op today — the red Contested-fact card is the corrective reference.
Implements B6 PRIORITY-TIER ordering, oldest-first within tier (starvation guard): ① REPORT/flagged ② claimed-official + MCC-elevated elected edits w/ badge ③ phone ④ <7d account — 🔨 priority int written at submit + index {placeId,status,priority,createdAt:1}; pagination ships with it (the 200-cap silently truncates today) · B5 OLD→NEW DIFF on every card — "Suresh Yadav → Ramesh Singh" — the steward's #1 gap (🔨 oldValue captured at SUBMIT onto the Contribution; today it's only written to Revision at approval, so pre-approval diff is impossible) · B7 trust line = account-age months + "3 accepted before" (🔨 stub createdAt + {contributorId,status} count; 🚫 Seva score on the card — noise); phone items carry a visual risk flag, source row stays · B8 desk diet: banner HALVED to role + place (NO Seva number), 🚫 role ladder, pull-to-refresh 🔨 missing · 🔴 B9 the red Contested-fact card: flag-as-incorrect is a SILENT NO-OP today (applyToTarget falls through) — REPORT becomes a first-class tier-① item, steward resolves keep vs revert · 🔨 A2 TTL tiers for steward-less places: field/POI auto-publish 14d · unclaimed-official non-phone 30d · PHONE NEVER · CLAIMED-OFFICIAL NEVER · A4 the S5 gates this queue assumes (<7d account, phone-PENDING, velocity→review-mode) are STILL UNBUILT — shared S5/S11 build batch.
Implements C10 CANNED REASON CHIPS above an optional free-text: needs-a-source is highlighted — THE social escape hatch in a village where steward and contributor share a chai stall ("system rule hai" beats "I don't believe you") · doesn't-match-current-record · person-no-longer-in-role · duplicate · phone-format · doesn't-seem-accurate. 🔨 chips become a SERVER ENUM + hybrid validation (S) — free text alone never replaces the key · the contributor-side outcome is a destination, never a verdict: "needs more info" framing, the word "rejected" is BANNED — 🔨 VERIFY the rejection actually notifies (likely missing today; must be a push) · C11 approve/reject = ONE TAP from the card; 🚫 partial-accept v1 (M + cognitive load); Seva on reject = none, no penalty (confirmed) — send-back is a request for evidence, not a strike.
Implements D14 "was: {old value}" collapsed line on EVERY revision row — same diff gap as B5, revert confidence comes from seeing what you'd restore; newest-first kept; autoPublished chip kept (it IS the patrol filter) vs steward-approved · D15 revert display is ACTION-framed — "Restored previous value · by Rajesh K." — never contributor-shaming; stewards always named (S5-A9); the original edit stays in the ledger, de-emphasized, strikethrough · the revert confirm shows the OLD VALUE inline before commit + "recorded with your name" · 🔴 D13 P0: today restoreTarget fires with NO audit record — the chain breaks exactly where power is exercised, and the revert-war guard only works once the rollback IS a revision. 🔨 rollbackOf field + create the revision BEFORE the target write (compensation logging exists; the gap-repair path is an admin runbook note) · ⏳ D16 contested-field admin-lock (3 flips/30d) = Phase-2 detection, absent here.
Implements C12 the promotion dialog gains the ONE briefing sentence — "Most edits go live instantly — your job is to patrol and fix, not approve everything" — this line decides whether stewardship reads as burden or empowerment; the first-visit empty desk REPEATS the patrol model · B8 empty state = "Your village is up to date" + History pointer; desk entry tile carries a pending-count BADGE (retention — the desk must call you back) · A3 steward nudge push after 5 days un-reviewed ("N edits waiting in {village}", steward-requested; rides SmartNotif) · E19 MCC briefing = a BANNER above the queue, 🚫 separate page; 🔨 dismiss state via badges $addToSet (XS). App-invisible governance cited, not depicted: A1 ancestor jurisdiction is the LIVE model formalized — local steward first in line, ancestor steward = FALLBACK never replacement; admin implicit everywhere · E17 demotion = ADMIN-ONLY v1, evidence 2 of {pair-anomaly, rejection-rate anomaly, contributor report}; Seva NEVER clawed back; 🚫 inactivity demotion without a "still active?" nudge · ⏳ E18 detection signals = Phase-2 CMS aggregations · ⏳ cross-place desk for multi-place stewards (single-place fine at launch).
Nothing waiting. Edits go live on their own — glance at the history when you visit and fix what's wrong.
View edit historyDECISIONS #7/#8: ONE language per screen via i18n — this frame renders S11·A end-to-end in hi. 🔨 F P0 i18n: the live "Steward Desk" page title is HARDCODED EN — a Hindi-set phone sees an English title on its most civic surface; full hi sweep rides this screen's build. Vocabulary locked here: tier labels ① शिकायत (report/contested) and ③ संपर्क (phone) — the risk words a rural steward actually uses; "स्रोत चाहिए" = the needs-a-source canned framing ("system rule hai" — the chip lets the steward cite the rule, not doubt the neighbour); points are सेवा everywhere (DECISIONS #10 — "karma" never renders, code ids may keep it); role = संरक्षक (per the S10 role set निवासी/सहयोगी/संरक्षक/अगुआ — display names are a separate per-locale task). Numerals, phone digits and the brand "Nyburs" stay Latin. Layout, tiers, diffs and ordering identical to S11·A.
Journey position: the desk is a PUSHED page reached from the Overview steward row / the entry tile (S11·D-5), never a place tab — frames carry the simple app bar (back chevron + title). S11 app-only / build-phase rulings cited in captions, NOT depicted: A1 ancestor jurisdiction is the LIVE canModerate model FORMALIZED (lead-verified: it already walks village→block→subDistrict→district, never state) — local steward first in line for notifications, ancestor steward = fallback never replacement, 🚫 cross-village peer review; admin implicit everywhere, the missing piece is the CMS monitoring view · A2 TTL tiers for steward-less PENDING (today NO TTL + >200 silently hidden): field/POI auto-publish 14d · unclaimed-official non-phone 30d · PHONE NEVER · CLAIMED-OFFICIAL NEVER; cron/lazy scan + approve pipeline callable from a worker (M), reviewedBy='system:ttl' marker; 🚫 auto-REJECT for low-risk · A3 5-day nudge rides SmartNotif · A4 the S5 classifyAutoPublish gates (<7d account, phone-PENDING, velocity→review-mode) are STILL spec-only — shared S5/S11 build batch · B5 oldValue captured at SUBMIT onto the Contribution (S) · B6 priority int at submit + index {placeId,status,priority,createdAt:1} + pagination (200-cap truncation is real) · B7 stub createdAt (XS) + {contributorId,status} accepted-count (S) · B8 pull-to-refresh missing; 2G kit = RefreshIndicator + avatar lazy/shimmer (F) · 🔴 B9 REPORT kind is a silent applyToTarget no-op — make it a first-class tier-① queue item · C10 canned reasons = SERVER ENUM + hybrid validation (S); VERIFY rejection notifies the contributor (push, "needs more info", never "rejected") · C11 🚫 partial-accept v1; Seva on reject = none · 🔴 D13 rollback writes its own revision + rollbackOf BEFORE the target write; compensation-gap repair path = admin runbook note (logged but unrepaired today) · ⏳ D16 contested-field admin-lock (3 flips/30d) = Phase 2 · E17 demotion ADMIN-ONLY v1, evidence 2 of {approval-pair anomaly, rejection-rate anomaly, contributor report}; Seva NOT clawed back (moderation right removed, earned points stay); 🚫 inactivity demotion without a "still active?" nudge · ⏳ E18 Phase-2 CMS detection aggregations, named now: places_pending_no_steward · approval-pair >60%/30d · rejection-rate <5%/>80% (n≥20) · pending_age_p95 (<14d) · rollback_frequency_by_field (≥3/30d) · phone_pending_age · mcc_queue_elevation_active; 🔨 {approverId,editorId} index when built; S10 founder cool-off still unbuilt (carry) · E19 MCC dismiss = badges $addToSet (XS); ⏳ cross-place desk (M) · F "Steward Desk" title hardcoded EN (i18n bug) + full hi sweep; steward-count query index note · G events: steward_desk_open · queue_item_judged{action,tier,secs} · canned_reason_used{key} · revert_tapped · ttl_autopublish_fired · promotion_briefing_seen; METRIC = steward 4-week action retention — % of new stewards acting in EACH of weeks 1–4, target >60% (a drop after week 2 means patrol feels like churn). DECISIONS #10: points render as Seva / सेवा everywhere — "karma" never reaches a screen.