DigitKard Ground Intelligence

The Record

A record you cannot edit is a record you can trust. जिस रिकॉर्ड को बदला न जा सके, उसी पर भरोसा किया जा सकता है।

Most systems store the present and call it the truth. This one stores what happened, in the order it happened, and lets the present be derived from it. ज़्यादातर व्यवस्थाएँ सिर्फ़ आज का हाल रखती हैं और उसी को सच कह देती हैं। यह व्यवस्था रखती है कि हुआ क्या, जिस क्रम में हुआ — और आज का हाल उसी से निकाला जाता है।

The problem this replaces

Six stages, one row, six overwrites. छह चरण, एक पंक्ति, छह बार मिटाई गई।

Live site today

The Aguwa registration form has six stages. Each stage writes into the same row, replacing what the previous stage put there. When the form is done, the row is correct — and everything that happened on the way to it is gone. अगुआ पंजीकरण फ़ॉर्म में छह चरण हैं। हर चरण उसी पंक्ति में लिखता है और पिछले चरण की बात मिटा देता है। फ़ॉर्म पूरा होने पर पंक्ति सही होती है — और उस तक पहुँचने में जो कुछ हुआ, वह ख़त्म।

Three questions become permanently unanswerable: where people stop, how long each stage takes, and what they corrected before submitting. तीन सवालों का जवाब हमेशा के लिए खो जाता है: लोग कहाँ रुकते हैं, हर चरण में कितना समय लगता है, और जमा करने से पहले उन्होंने क्या सुधारा।

Here

The row still holds current state — the form works exactly as it did. Alongside it, each stage transition appends an event that is never touched again. पंक्ति अब भी मौजूदा हाल रखती है — फ़ॉर्म ठीक वैसे ही चलता है जैसे पहले। उसके साथ-साथ, हर चरण-बदलाव एक घटना जोड़ता है जिसे दोबारा कभी छुआ नहीं जाता।

Time-on-stage is the gap between two timestamps. Drop-off is a stage entered with no matching submit. Neither costs the user a single extra tap. चरण में लगा समय दो समयों का अंतर है। छूटना यानी वह चरण जिसमें प्रवेश हुआ पर जमा नहीं हुआ। दोनों में उपयोगकर्ता को एक भी अतिरिक्त टैप नहीं करना पड़ता।

Rule 02, in full

Every success has a failure twin. हर सफलता का एक असफलता-जोड़ा है।

Systems that log only what worked produce research that only ever flatters them. The twin is not an error log — it is the more informative half. जो व्यवस्था सिर्फ़ सफल काम लिखती है, उसका शोध सिर्फ़ उसकी तारीफ़ करता है। यह जोड़ा कोई एरर-लॉग नहीं है — यही ज़्यादा बताने वाला आधा हिस्सा है।

Recorded on successसफलता पर Recorded on failureअसफलता पर What the failure tells usअसफलता क्या बताती है
registration_stage_submitted registration_stage_abandoned Exactly which question ends the conversation. ठीक कौन-सा सवाल बात ख़त्म करा देता है।
profile_created profile_validation_rejected What our form demands that the ground cannot supply. हमारा फ़ॉर्म क्या माँगता है जो ज़मीन दे ही नहीं सकती।
match_search_returned match_search_empty Which pools we cannot serve at all — the clearest market signal there is. किन समूहों को हम सेवा दे ही नहीं सकते — बाज़ार का सबसे साफ़ संकेत यही है।
payment_captured payment_failed Whether the price or the payment rail is the obstacle. रुकावट क़ीमत है या भुगतान का रास्ता।
login_succeeded login_failed How often a returning partner is simply locked out. लौटने वाला साथी कितनी बार बस बाहर ही रह जाता है।
profile_status_changed profile_status_changed  (reason required) Why a real person was rejected — a reason code, never a bare status. किसी असली व्यक्ति को क्यों अस्वीकार किया गया — कारण-कोड, सिर्फ़ स्थिति नहीं।

The interface constraint

If it can be derived, it is never asked. जो ख़ुद निकाला जा सकता है, वह कभी पूछा नहीं जाता।

The person filling this form is often using a smartphone for the first time, on a cheap handset, on a slow connection, frequently with someone else reading the screen aloud to them. Research must never make that screen heavier. यह फ़ॉर्म भरने वाला अक्सर पहली बार स्मार्टफ़ोन चला रहा होता है — सस्ता फ़ोन, धीमा नेटवर्क, और कई बार कोई और उसे स्क्रीन पढ़कर सुना रहा होता है। शोध की वजह से वह स्क्रीन कभी भारी नहीं होनी चाहिए।

So the department is not allowed to add a field. Not one. Everything below is already available without asking anybody anything: इसलिए विभाग को कोई नया खाना जोड़ने की इजाज़त नहीं है। एक भी नहीं। नीचे लिखी हर चीज़ बिना किसी से कुछ पूछे पहले से मिल जाती है:

  • Time on stage
    Two consecutive event timestamps, subtracted. लगातार दो घटनाओं के समय का अंतर।
  • Drop-off point
    A stage entered with no matching submit before the session ends. वह चरण जिसमें प्रवेश हुआ, पर सत्र ख़त्म होने तक जमा नहीं हुआ।
  • Connection quality
    Request metadata — round-trip time, retries, payload size. अनुरोध का मेटाडेटा — समय, दोबारा कोशिशें, आकार।
  • Device class
    Screen size and user agent, already sent by every browser. स्क्रीन का आकार और ब्राउज़र की जानकारी, जो हर ब्राउज़र पहले से भेजता है।
  • Return behaviour
    Whether a partner comes back, and after how long. साथी वापस आता है या नहीं, और कितने समय बाद।
  • Correction habit
    What was typed, then changed, before submitting. जो लिखा गया, फिर जमा करने से पहले बदल दिया गया।

The one thing we do add is a refusal option. On money questions the form offers "prefer not to say" instead of forcing a number. A refusal is recorded as a refusal — it is honest data, and it is far more useful than the invented figure it replaces. हमने सिर्फ़ एक चीज़ जोड़ी है — मना करने का विकल्प। पैसे वाले सवालों में फ़ॉर्म संख्या भरने पर मजबूर करने के बजाय "बताना नहीं चाहते" देता है। मना करना, मना करने की तरह ही दर्ज होता है — यह ईमानदार आँकड़ा है, और उस गढ़े हुए नंबर से कहीं ज़्यादा काम का है जिसकी वह जगह लेता है।

When the record is wrong

A mistake is corrected by writing, not by erasing. ग़लती लिखकर सुधारी जाती है, मिटाकर नहीं।

Nothing in the log is ever updated or deleted — the storage rules deny both to every client, not just by convention. A correction is a new event carrying correctsEventId, pointing back at the one it supersedes. लॉग में कुछ भी न बदला जाता है, न मिटाया जाता है — भंडारण के नियम हर क्लाइंट को दोनों से रोकते हैं, यह सिर्फ़ रिवाज़ नहीं है। सुधार एक नई घटना होती है जिसमें correctsEventId होता है, जो पुरानी घटना की ओर इशारा करता है।

The original stays exactly as it was written — because that it was wrong, and when somebody noticed, is itself the finding. मूल घटना जैसी लिखी गई थी, वैसी ही रहती है — क्योंकि वह ग़लत थी, और किसी ने कब पकड़ा, यही अपने आप में नतीजा है।

day 1 · 10:22 profile_created  eventId=e_8812  village=…0417 stands
day 9 · 16:40 profile_corrected  correctsEventId=e_8812  village=…0419 supersedes

Both rows live forever. The second one is the current truth; the first one is the evidence that our village coding is hard to get right on the first try. दोनों पंक्तियाँ हमेशा रहेंगी। दूसरी आज का सच है; पहली इस बात का सबूत है कि गाँव का कोड पहली बार में सही डालना आसान नहीं है।

The shape of one event

What every row must carry.हर पंक्ति में क्या होना ज़रूरी है।

events/{eventId}
  eventType      string      registration_stage_submitted, match_search_empty, …
  occurredAt     timestamp
  actorId        string      MANDATORY — a write without one is dropped
  actorRole      string      partner | member | admin | system
  channelId      string      → channels/{channelId}, never a hardcoded enum

  districtCode   string      LGD — the pilot boundary
  blockCode      string      LGD
  panchayatCode  string      LGD
  villageCode    string      LGD, where known
  wardCode       string      LGD — the last mile

  payload        map         event-type specific
  schemaVersion  number
  correctsEventId string     present only on a correction

Geography is denormalised onto every single event, deliberately. A ward-level question must never require a join to answer. The district is a constant during the pilot, but it is written anyway, so the same log stays valid the day a second district is added. भूगोल जान-बूझकर हर घटना पर दोहराया जाता है। वार्ड-स्तर के सवाल का जवाब देने के लिए कभी जोड़-तोड़ न करनी पड़े। पायलट के दौरान ज़िला एक ही रहेगा, फिर भी लिखा जाता है — ताकि जिस दिन दूसरा ज़िला जुड़े, वही लॉग चलता रहे।