Authoring a pack? Start with
AUTHORING_QUEST_PACKS.md— the single guided scaffold→author→lint→import→version walkthrough. This file is the model + validation-engine deep dive behind it.
A GameDay succeeds or fails on whether participants trust the scoring.
System-table inference alone is too blunt. For example, system tables can tell that a user ran a query or created a pipeline, but they cannot reliably prove that a team:
- produced the required business output
- used the intended governance pattern
- created the correct object in the correct schema
- passed data quality constraints
- optimized cost or performance
- handled an incident scenario correctly
- wrote code that produces the expected result
Therefore, validation must become a first-class product domain.
A versioned package of event content.
Fields:
pack_idversiontitledescriptionaudienceduration_minutesdifficultyscenario_narrativelearning_objectivesrequired_capabilitiesquestsresourcesfacilitator_notes
A group of related tasks within a story arc.
Fields:
quest_idtitlenarrativecategorydifficultybase_pointsunlock_ruletasks
A concrete objective that can be validated.
Fields:
task_idtitleobjectiveinstructionssuccess_criteriapointsvalidatorshintsevidence_visible_to_playerfacilitator_notes
A machine-readable rule that decides whether an attempt passes.
Fields:
validator_idtypemode:syncorasyncparametersexpected_resulttimeout_secondsretry_policysafe_error_messageevidence_policy
A player's or team's submission for a task.
Fields:
attempt_idevent_idteam_iduser_idtask_idsubmission_payloadstatussubmitted_atcompleted_at
The normalized output of one validator.
Fields:
validation_result_idattempt_idvalidator_idstatus:passed,failed,error,skippedscore_deltamessageevidence_jsonstarted_atcompleted_at
Append-only points ledger.
Fields:
scoring_event_idevent_idteam_iduser_idtask_idsource_typesource_idpoints_deltareasoncreated_at
Runs a safe SQL query and checks the result.
Use cases:
- table exists
- row count expected
- data quality rule met
- query returns expected value
- aggregation matches target output
- view/materialized view created
- governance table function works
Example:
validators:
- id: validate_customer_gold_table
type: sql_assertion
mode: sync
warehouse: event_default
statement: |
SELECT COUNT(*) AS cnt
FROM ${team_catalog}.${team_schema}.customer_gold
WHERE customer_id IS NOT NULL
expect:
operator: ">="
value: 1000Safety rules:
- default read-only SQL
- block destructive statements unless explicitly allowlisted
- template variables are validated
- queries run under scoped service principal
- result evidence is truncated
Uses the Databricks SDK to inspect workspace objects.
Use cases:
- job exists
- job has schedule
- pipeline exists
- serving endpoint exists and is ready
- vector search index exists
- Unity Catalog grants are correct
- dashboard exists
Example:
validators:
- id: validate_job_schedule
type: databricks_sdk
check: job_exists_with_schedule
mode: sync
params:
name_pattern: "${team_prefix}-daily-ingest"
trigger_type: "CRON"Queries system tables to verify platform activity.
Use cases:
- query was run after event start
- job ran successfully
- pipeline update completed
- model serving endpoint was invoked
- team consumed specific DBU product type
Example:
validators:
- id: validate_pipeline_run
type: system_table
table: system.lakeflow.pipeline_update_timeline
mode: async
lookback: event_window
condition: |
result_state = 'COMPLETED'
AND run_as_user_name IN (${team_members})
AND period_start_time >= ${event_start}Runs a Databricks notebook that contains custom validation logic.
Use cases:
- complex business logic
- multi-step checks
- code-heavy validation
- generated artifacts
- model evaluation
Required notebook output:
{
"status": "passed",
"message": "Gold table passed all checks",
"score_delta": 200,
"evidence": {
"checks_passed": 7,
"rows_validated": 10000
}
}Runs a lightweight Python validation function or test suite.
Use cases:
- inspect code submitted by participant
- run pytest-style checks
- validate a function output
- validate generated config files
Pattern:
- participant submits repo path, file path, or notebook path
- validator worker checks out/reads artifact
- tests run in controlled job environment
- result is normalized
Calls an endpoint and validates response.
Use cases:
- Databricks App task
- model endpoint invocation
- external API simulation
- agent endpoint response check
A host can manually mark a task as passed, failed, or partially passed.
Use cases:
- subjective presentation tasks
- edge cases
- validation outage
- bonus challenge judging
submitted
↓
queued
↓
running
↓
passed | failed | error | timed_out | cancelled
Recommended scoring fields:
scoring:
base_points: 200
first_blood_bonus: 50
speed_bonus:
enabled: true
max_bonus: 100
decay_after_minutes: 30
hint_penalties:
first_hint: -10
second_hint: -25
third_hint: -50
max_attempts_without_penalty: 3
attempt_penalty_after_max: -5
partial_credit: trueEach task should only award base points once per team unless explicitly repeatable.
Use idempotency key:
event_id + team_id + task_id + scoring_rule_id
Manual overrides are separate scoring events and never mutate original events.
Validators should produce evidence, but not all evidence should be exposed to players.
Recommended fields:
public_message: safe player-facing resultprivate_message: host-facing diagnosticevidence_json: structured evidenceraw_output_location: optional secure storage pointerredaction_status
Validation must not become an arbitrary code execution escape hatch.
Controls:
- validator type allowlist
- per-event capability allowlist
- read-only SQL default
- validator timeouts
- output truncation
- scoped service principal
- team resource namespace restrictions
- denylist for destructive statements
- host-only notebook validators
- audit all validation requests and results
Start with:
- SQL assertion
- Databricks SDK object check
- Manual host validation
Then add:
- System table validator
- Notebook validator
- Python code validator
- REST/API validator
The first-class validation engine ships with sql_assertion and manual:
- Code lives in
app/validators/(base.py,safety.py,sql_assertion.py,manual.py); dispatch + aggregation inapp/services/validation_engine.py; the idempotent award inapp/services/scoring_service.py(+app/repositories/scoring.py). - Submission endpoint:
POST /api/events/{event_id}/tasks/{task_id}/attempts(seedocs/08). It runs every enabled validator, persists onevalidation_resultsrow each, transitions thetask_attemptsrow, and — on a passing aggregate — writes a singlescoring_eventsrow. - Safety (read-only SQL):
sql_assertionallows exactly oneSELECT/WITHstatement; destructive/DDL/DML verbs and stacked statements are rejected.${...}template slots resolve only from server-provided variables (team_catalog,team_schema,team_id,event_id) — a player cannot introduce a slot or inject SQL through one. Evidence is row/char truncated. - Player-safe errors: validators never raise to the player; a bad
config/timeout/exec failure becomes an
erroroutcome with a safepublic_message, while the detailedprivate_messageis kept host-side. - Idempotency: base points are awarded once per scope — team in
standalone/master, workspace in a federation child — enforced by the
scoring_events.idempotency_keyUNIQUE constraint.
databricks_sdk, system_table, notebook, python_code, and rest_api
remain accepted by the authoring schema and are dispatched as skipped (with a
host breadcrumb) until their executors land in later PRs.
Every quest task must include:
- objective
- success criteria
- one or more validators
- safe failure message
- facilitator note
- estimated time
- points
- hint ladder
If a task cannot be validated automatically, it must declare manual_validation_required: true.