apiVersion: v3.1.0
kind: DataContract
id: education.georgia_milestones_end_of_course_lexile
name: georgia_milestones_end_of_course_lexile
version: 1.0.0
status: active
domain: education
tenant: georgia-public-data
description:
  purpose: 'Governor''s Office of Student Achievement (GOSA) Georgia Milestones End-of-Course (EOC) Lexile
    assessment dataset. Reports Lexile reading-measure distributions derived from Georgia''s two English
    Language Arts EOC courses (9th Grade Literature and Composition, American Literature and Composition).
    Each row is one (entity x subject) combination with five measures: total students tested, students
    with a Lexile measure, students without a Lexile score, students with Lexile at or above the grade-level
    midpoint (the ''on-track reader'' threshold), and the average Lexile measure. Coverage is school years
    2014-15 through 2023-24 (2019-20 absent — EOC testing suspended due to COVID-19) at state, district,
    and school detail levels. No demographic breakdown — every row is implicitly ''All Students''.'
  usage: Star-schema fact table. Join the districts dimension on district_code; the schools dimension
    on district_code + school_code. Read directly with DuckDB over Parquet.
  limitations: Suppressed cells are NULL (not zero). State rows have NULL district_code and school_code.
    District rows have NULL school_code.
tags:
- education
- governor's office of student achievement
- georgia_milestones_end_of_course_lexile
servers:
- server: s3_gold
  type: s3
  location: s3://georgia-data-gold/education/georgia_milestones_end_of_course_lexile/**/*.parquet
  format: parquet
- server: local_gold
  type: local
  path: data/gold/education/georgia_milestones_end_of_course_lexile/**/*.parquet
  format: parquet
schema:
- name: georgia_milestones_end_of_course_lexile
  logicalType: object
  physicalType: parquet
  physicalName: georgia_milestones_end_of_course_lexile
  description: georgia_milestones_end_of_course_lexile fact table, year-partitioned Parquet (split by
    detail level where present).
  dataGranularityDescription: One row per year, district_code, school_code, subject (geography columns
    are NULL at higher aggregation levels).
  customProperties:
  - property: sub_topic
    value: gosa
  - property: detail_levels
    value:
    - schools
    - districts
    - states
  - property: default_detail
    value: schools
  - property: grain
    value:
    - year
    - district_code
    - school_code
    - subject
  - property: key_metric
    value: avg_lexile_score
  - property: null_semantics
    value:
      suppressed_to_null: true
      zero_is_real: true
  - property: partition_columns
    value:
    - year
  - property: path_template
    value: education/georgia_milestones_end_of_course_lexile/year={year}/{detail}.parquet
  - property: foreign_keys
    value:
    - column: district_code
      target_object: districts
      target_columns:
      - district_code
      attribute_columns:
      - district_name
      - district_census_id
      - district_type
      scope: domain
    - column: school_code
      target_object: schools
      target_columns:
      - district_code
      - school_code
      attribute_columns:
      - school_name
      scope: domain
  - property: example_queries
    value:
    - description: Latest year (2024), schools detail
      query: SELECT * FROM georgia_milestones_end_of_course_lexile WHERE year = 2024 LIMIT 100
    - description: District 601 in 2024
      query: SELECT * FROM georgia_milestones_end_of_course_lexile WHERE district_code = '601' AND year
        = 2024 LIMIT 100
    - description: Filter by subject = american_literature_and_composition
      query: SELECT * FROM georgia_milestones_end_of_course_lexile WHERE subject = 'american_literature_and_composition'
        AND year = 2024 LIMIT 100
  properties:
  - name: year
    logicalType: integer
    physicalType: int
    required: true
    description: Ending calendar year of the school year (e.g., 2024 = 2023-24). Derived from the filename
      and cross-checked against the bronze SCHOOL_YEAR column. 2020 is absent (EOC testing suspended during
      COVID-19 closures).
    examples:
    - 2024
    customProperties:
    - property: column_role
      value: year
    - property: label
      value: Year
    primaryKey: true
    primaryKeyPosition: 1
  - name: district_code
    logicalType: string
    physicalType: string
    required: false
    description: 'GOSA district code (FK to districts dimension): 3-digit zero-padded county/city codes
      or 7-digit state-charter codes. NULL on state-level rows.'
    examples:
    - '601'
    relationships:
    - to: districts.district_code
    customProperties:
    - property: column_role
      value: fk_district
    - property: label
      value: District Code
    primaryKey: true
    primaryKeyPosition: 2
  - name: school_code
    logicalType: string
    physicalType: string
    required: false
    description: GOSA school code, zero-padded to 4 characters (composite FK to schools dimension with
      district_code; not globally unique on its own). NULL on district- and state-level rows.
    examples:
    - '0100'
    relationships:
    - to: schools.district_code
    - to: schools.school_code
    customProperties:
    - property: column_role
      value: fk_school
    - property: label
      value: School Code
    primaryKey: true
    primaryKeyPosition: 3
  - name: subject
    logicalType: string
    physicalType: string
    required: true
    description: ELA EOC course this row measures, snake_case canonical. 9th_grade_literature_and_composition
      is present 2015-2021 (only 84 rows in 2021) and retired after 2021 — a real curriculum change (GOSA
      moved 9th-grade ELA off the EOC program), not a relabeling. american_literature_and_composition
      is present every year and is the sole subject from 2022.
    examples:
    - 'american_literature_and_composition'
    enum:
    - '9th_grade_literature_and_composition'
    - 'american_literature_and_composition'
    customProperties:
    - property: column_role
      value: categorical
    - property: label
      value: Subject
    - property: short_description
      value: 'Which ELA End-of-Course exam the row covers: 9th Grade Literature (through 2021) or American
        Literature.'
    - property: has_total
      value: false
    - property: key_metric_grain_contributor
      value: true
    primaryKey: true
    primaryKeyPosition: 4
  - name: num_tested
    logicalType: integer
    physicalType: bigint
    required: false
    description: Count of students who took the subject's EOC. Bronze TOTAL_STUDENTS_TESTED. NULL when
      the source cell is blank (2015-2019 — those files contain no TFS) or TFS-suppressed (2021-2024);
      4-18% of rows depending on year.
    examples:
    - 287
    customProperties:
    - property: column_role
      value: metric
    - property: label
      value: Number Tested
    - property: unit
      value: count
    - property: null_meaning
      value: '2015-2019: genuinely blank source cell; 2021-2024: GOSA TFS (''Too Few Students'') suppression.'
  - name: num_with_lexile
    logicalType: integer
    physicalType: bigint
    required: false
    description: Count of tested students whose EOC produced a usable Lexile measure — equal to or slightly
      below num_tested, never above it (enforced). Reported exactly when avg_lexile_score is reported
      (enforced biconditional). Bronze STUDENTS_WITH_LEXILE; NULL when blank (2015-2019) or TFS-suppressed
      (2021-2024). In all years only 2 rows have num_tested reported with this column missing (2015 Polk
      County school 0207; 2016 Bleckley County school 0115 — blank cells, not TFS).
    examples:
    - 287
    customProperties:
    - property: column_role
      value: metric
    - property: label
      value: Number with Lexile
    - property: unit
      value: count
    - property: null_meaning
      value: '2015-2019: genuinely blank source cell; 2021-2024: GOSA TFS suppression.'
    - property: metric_component
      value: denominator
  - name: num_without_lexile
    logicalType: integer
    physicalType: bigint
    required: false
    description: 'Count of tested students who did NOT receive a usable Lexile measure, as published by
      GOSA (bronze NO_LEXILE_SCORE). This is an independently reported source count, NOT the arithmetic
      complement num_tested - num_with_lexile: of the 140 rows (all years) where all three counts are
      numeric, 45 disagree with that derivation (by up to 99 students), so the published column is retained
      rather than derived and no with+without=tested check is enforced. Heavily suppressed (~94-99% NULL).'
    examples:
    - 30
    customProperties:
    - property: column_role
      value: metric
    - property: label
      value: Number Without Lexile
    - property: unit
      value: count
    - property: null_meaning
      value: Blank source cell (2015-2019) or GOSA TFS suppression (2021-2024) — ~94-99%% of rows in every
        year; only 1-37 rows per year carry a numeric value.
  - name: num_at_or_above_lexile_midpoint
    logicalType: integer
    physicalType: bigint
    required: false
    description: 'Count of students whose Lexile measure was at or above the midpoint of the course''s
      Lexile range (GOSA''s ''on-track reader'' / grade-level threshold: 1050L for 9th Grade Literature,
      1185L for American Literature). A raw COUNT, not a percentage (2024 state row: 69,660 of 132,835
      students with a Lexile = 52.4%) — derive a share by dividing by num_with_lexile (the population
      with a valid Lexile), not num_tested. Never exceeds num_with_lexile (enforced). Bronze LEXILE_ON_OR_ABOVE_MIDPOINT;
      NULL when suppressed.'
    examples:
    - 65
    customProperties:
    - property: column_role
      value: metric
    - property: label
      value: Number at or Above Lexile Midpoint
    - property: unit
      value: count
    - property: null_meaning
      value: Blank source cell (2015-2019) or GOSA TFS suppression (2021-2024) — the most-missing count
        after num_without_lexile (~10-29%% of rows by year).
  - name: avg_lexile_score
    logicalType: number
    physicalType: double
    required: false
    description: Average Lexile reading measure among students who received one, reported to one decimal
      place. The Lexile reader scale runs from below 0L (BR / Beginning Reader) to above 2000L; the contract
      enforces 0-2000 for these entity-level averages (observed range 707.0-1679.3 across all years and
      detail levels — a below-0 BR average is unreachable for an EOC cohort). NOT a percentage — no 0-1
      rescaling; the natural Lexile scale is preserved. Reported exactly when num_with_lexile is reported
      (enforced biconditional). Bronze AVG_LEXILE_SCORE; NULL when suppressed.
    examples:
    - 1119.9
    customProperties:
    - property: column_role
      value: metric
    - property: label
      value: Average Lexile Score
    - property: short_description
      value: Average Lexile reading measure (on the natural Lexile scale, not a percentage) among students
        who received one.
    - property: unit
      value: score
    - property: value_min
      value: 0
    - property: value_max
      value: 2000
    - property: null_meaning
      value: Blank source cell (2015-2019) or GOSA TFS suppression (2021-2024) — exactly when num_with_lexile
        is missing.
    - property: key_metric
      value: true
  quality:
  - type: sql
    name: non_empty
    description: The dataset has at least one row.
    dimension: completeness
    query: SELECT COUNT(*) FROM {object}
    mustBeGreaterThan: 0
  - type: sql
    name: subject_in_allowed_values
    description: subject is one of the 2 canonical codes.
    dimension: conformity
    query: SELECT COUNT(*) FROM {object} WHERE subject IS NOT NULL AND subject NOT IN ('9th_grade_literature_and_composition',
      'american_literature_and_composition')
    mustBe: 0
  - type: sql
    name: num_tested_non_negative
    description: num_tested is a count (>= 0).
    dimension: accuracy
    query: SELECT COUNT(*) FROM {object} WHERE num_tested IS NOT NULL AND num_tested < 0
    mustBe: 0
  - type: sql
    name: num_with_lexile_non_negative
    description: num_with_lexile is a count (>= 0).
    dimension: accuracy
    query: SELECT COUNT(*) FROM {object} WHERE num_with_lexile IS NOT NULL AND num_with_lexile < 0
    mustBe: 0
  - type: sql
    name: num_without_lexile_non_negative
    description: num_without_lexile is a count (>= 0).
    dimension: accuracy
    query: SELECT COUNT(*) FROM {object} WHERE num_without_lexile IS NOT NULL AND num_without_lexile <
      0
    mustBe: 0
  - type: sql
    name: num_at_or_above_lexile_midpoint_non_negative
    description: num_at_or_above_lexile_midpoint is a count (>= 0).
    dimension: accuracy
    query: SELECT COUNT(*) FROM {object} WHERE num_at_or_above_lexile_midpoint IS NOT NULL AND num_at_or_above_lexile_midpoint
      < 0
    mustBe: 0
  - type: sql
    name: avg_lexile_score_within_range
    description: avg_lexile_score is within its declared [0, 2000] range.
    dimension: accuracy
    query: SELECT COUNT(*) FROM {object} WHERE avg_lexile_score IS NOT NULL AND (avg_lexile_score < 0
      OR avg_lexile_score > 2000)
    mustBe: 0
  - type: sql
    name: lexile_population_within_tested
    description: num_with_lexile counts a subset of tested students, so it must not exceed num_tested
      where both are present (verified in bronze 2015-2024 with zero violations).
    dimension: consistency
    query: SELECT COUNT(*) FROM {object} WHERE num_with_lexile IS NOT NULL AND num_tested IS NOT NULL
      AND num_with_lexile > num_tested
    mustBe: 0
  - type: sql
    name: no_lexile_count_within_tested
    description: 'num_without_lexile counts a subset of tested students, so it must not exceed num_tested
      where both are present (verified in bronze 2015-2024: zero violations across all 140 fully-observable
      rows). Completes the subset-check family alongside num_with_lexile and the midpoint count.'
    dimension: consistency
    query: SELECT COUNT(*) FROM {object} WHERE num_without_lexile IS NOT NULL AND num_tested IS NOT NULL
      AND num_without_lexile > num_tested
    mustBe: 0
  - type: sql
    name: midpoint_count_within_lexile_population
    description: num_at_or_above_lexile_midpoint counts a subset of the students with a Lexile measure,
      so it must not exceed num_with_lexile where both are present (verified in bronze 2015-2024 with
      zero violations).
    dimension: consistency
    query: SELECT COUNT(*) FROM {object} WHERE num_at_or_above_lexile_midpoint IS NOT NULL AND num_with_lexile
      IS NOT NULL AND num_at_or_above_lexile_midpoint > num_with_lexile
    mustBe: 0
  - type: sql
    name: avg_lexile_reported_iff_lexile_population_reported
    description: 'avg_lexile_score and num_with_lexile are statistics of the same population (students
      who received a Lexile) and are suppressed together: each is NULL exactly when the other is (verified
      in bronze 2015-2024 with zero violations in either direction).'
    dimension: consistency
    query: SELECT COUNT(*) FROM {object} WHERE (avg_lexile_score IS NULL) != (num_with_lexile IS NULL)
    mustBe: 0
  - type: sql
    name: midpoint_reported_implies_lexile_population_reported
    description: A reported num_at_or_above_lexile_midpoint implies its denominator population num_with_lexile
      is reported (verified in bronze 2015-2024 with zero violations; the converse does not hold — the
      midpoint count is suppressed more often).
    dimension: completeness
    query: SELECT COUNT(*) FROM {object} WHERE num_at_or_above_lexile_midpoint IS NOT NULL AND num_with_lexile
      IS NULL
    mustBe: 0
  - type: sql
    name: lexile_population_reported_implies_tested_reported
    description: A reported num_with_lexile implies num_tested is reported (verified in bronze 2015-2024
      with zero violations; the converse has exactly 2 source exceptions — 2015 Polk County school 0207
      and 2016 Bleckley County school 0115 — so only this direction is enforced).
    dimension: completeness
    query: SELECT COUNT(*) FROM {object} WHERE num_with_lexile IS NOT NULL AND num_tested IS NULL
    mustBe: 0
  - type: sql
    name: ninth_grade_subject_retired_after_2021
    description: 'The 9th Grade Literature and Composition EOC was retired after 2021 (GOSA moved 9th-grade
      ELA off the EOC program) — it must never appear in later years (verified: 2022-2024 bronze contains
      only American Literature rows).'
    dimension: consistency
    query: SELECT COUNT(*) FROM {object} WHERE subject = '9th_grade_literature_and_composition' AND year
      > 2021
    mustBe: 0
customProperties:
- property: title
  value: Georgia Milestones EOC Lexile Reading Scores
- property: summary
  value: Lexile reading-measure distributions from Georgia's two ELA End-of-Course exams by school, district,
    and state, 2015-2024.
- property: source
  value: Governor's Office of Student Achievement (GOSA)
- property: source_url
  value: https://gosa.georgia.gov/dashboards-data-report-card/downloadable-data
- property: update_frequency
  value: annual
- property: year_range
  value: 2015-2024
- property: schema_hash
  value: 91988a21c74436d9a28b26a926ea0b21fb149ac023b7482cdca1d4d78790f691
- property: available_years
  value:
  - 2015
  - 2016
  - 2017
  - 2018
  - 2019
  - 2021
  - 2022
  - 2023
  - 2024
- property: year_gaps
  value:
  - 2020
