Methodology
This page describes exactly how Vidhata currently computes question probability, individual Brier scores, user averages, and leaderboard ordering in the present web-only architecture (Firestore + Auth). It reflects the current implementation, including safeguards, constraints, and manual admin operations that will later move to Cloud Functions.
1. Question Lifecycle and Timeline
Each prediction question moves through a strict lifecycle. Forecasting is only accepted while
status is open. Admin can move a question to closed (forecasting
stopped, awaiting official outcome), then to resolved.
| Stage | Who | Data Written | Timing |
|---|---|---|---|
| Create Question | Authenticated user | questions/{id} with title, description, category, probability,
resolutionDate, effectiveCloseAt, resolutionCriteria, createdBy, createdByName,
createdAt, updatedAt, status=open |
One-time at creation |
| Submit Forecast | Authenticated forecaster | History entry in forecasts + overwrite latest in
latestForecastByUser/{uid} |
Any time while open, but max once per 5 minutes per user/question |
| Recompute Aggregate | Admin | Updates question probability and forecastCount |
Manual button now; target is automated trigger later |
| Resolve | Admin | Sets status=resolved, resolutionOutcome (0/1), resolvedAt, resolutionSource, effectiveCloseAt | After external event is deterministically known |
| Score | Admin | Writes per-user score docs, updates user aggregates + leaderboard docs, marks scoredAt on question | After resolution, repeatable safely for idempotent recalculation |
2. Forecast Data Model and Anti-Spam Rules
Vidhata keeps both immutable history and one authoritative latest forecast per user. This allows auditability plus fast reads for aggregation/scoring.
questions/{id}/forecasts/{autoId}: append-only history of submissions.questions/{id}/latestForecastByUser/{uid}: single latest forecast used for aggregation and scoring.- Security rules enforce
0 <= probability <= 1. - Security rules enforce question must be open.
- Security rules block forecast writes after
effectiveCloseAtTswhen set. - Security rules enforce a 5-minute cooldown per user per question, based on
updatedAt.
3. Question Probability Aggregation
Current aggregate uses latest forecast per user with skill weighting.
- Source: all docs from
latestForecastByUser. - Each probability is clamped to [0,1] before inclusion.
- Skill weights use
1 - brierScoreAvgwith operational safeguards. - For low-history users (resolvedCount below threshold), a default neutral weight is used.
- Skill weights are clamped to a configured range to prevent dominance.
- Stored value is rounded to 4 decimals before write.
- Output fields on question doc:
probability,forecastCount,updatedAt.
4. Individual Brier Score Calculation
Vidhata uses time-weighted Brier per resolved question. Lower is better.
Interpretation:
- Forecasts that were accurate for longer durations get more credit.
- Last-minute obvious updates contribute less because their time exposure is small.
- Perfect prediction path yields 0.0. Worst possible path approaches 1.0.
- If no interval duration can be formed (edge case), the final pre-close forecast is used as fallback for that question score.
For each resolved question, Vidhata computes one time-weighted score per user and writes it to
users/{uid}/scores/{questionId}.
5. User Aggregate Score (Profile-Level)
After per-question scores are written, each user gets an aggregate average over their scored resolved questions.
- Stored on
users/{uid}asbrierScoreAvgandresolvedCount. lastScoredAtandupdatedAtare updated at run time.- Rules allow only admin to write these scoring summary fields.
6. Leaderboard Computation
Leaderboard reads sanitized public docs from leaderboard/{uid}, populated from the
scoring pass.
- Sort order: ascending
brierScoreAvg(lower is better). - Tie-break: higher
resolvedCountfirst. - Qualified board threshold:
resolvedCount >= 10. - Developing board:
resolvedCount < 10.
7. Resolution Standards and Governance
Each question must include resolution criteria and a source field is required at resolution. This keeps scores auditable.
resolutionCriteriais specified up front when question is created.effectiveCloseAtis used as the scoring cutoff when uncertainty is effectively over before nominal resolution date.effectiveCloseAtTs(timestamp) is used for rule-level forecast cutoff enforcement.resolutionSourcemust be supplied when resolving.resolvedAtstores when resolution was recorded.scoredAt+scoredForResolvedAtidentify whether scoring is current for that resolution state.
8. Current Limitations and Planned Upgrade
- Aggregation and scoring are currently admin-triggered from UI buttons.
- This is operationally acceptable for early stage and Spark constraints.
- On Blaze, the same logic should move to Cloud Functions to ensure automatic, tamper-resistant, low-latency updates.
- When moved, admin UI buttons can be removed and rules tightened further.