# Worked Example: Regenerate MAP Quadrants And Verify Surface Answer Key

This example proves the pack asks the surface correctly. It calls the live Results Alpha API, asks for MAP Quadrants under 2025 and 2020 norms, and verifies the 2025 response against the surface-owned answer key.

It does not bundle norms data, select retakes, parse terms, compute Growth X, compute quadrants, or hash report rows locally.

Prerequisites: `curl` and `jq`.

## 1. Mint Demo Token

```sh
export RESULTS_BASE_URL="${RESULTS_BASE_URL:-https://platform3-andymontgomery-9773s-projects.vercel.app/results/alpha/implementation/api}"
export RESULTS_TOKEN="$(curl -fsS -X POST "$RESULTS_BASE_URL/dev/mint?tenantId=demo" | jq -r '.token')"
export COMMON_2025="subject=math&canonicalTermId=term_2025_26_spring&growthWindow=fall_to_spring&normsSet=2025"
export COMMON_2020="subject=math&canonicalTermId=term_2025_26_spring&growthWindow=fall_to_spring&normsSet=2020"
```

## 2. Read The Descriptor

```sh
curl -fsS "$RESULTS_BASE_URL" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{module,surface,docs,endpoints:(.endpoints|length)}'
```

Expected shape:

```json
{
  "module": "results",
  "surface": "alpha",
  "endpoints": 36
}
```

## 3. Regenerate MAP Quadrants Under 2025 Norms

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/reports/map-quadrants?$COMMON_2025" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  > /tmp/results-map-quadrants-2025.json

jq '{count,hash:.meta.resultHash,first:.data[0]}' /tmp/results-map-quadrants-2025.json
```

Use the returned rows as the source of truth for `student_id`, `rit`, `growth_x`, and `quadrant`. Do not copy demo values into the client.

## 4. Verify Against The Surface Answer Key

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/reports/answer-key?normsSet=2025" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  > /tmp/results-answer-key-2025.json

REPORT_HASH="$(jq -r '.meta.resultHash' /tmp/results-map-quadrants-2025.json)"
REPORT_COUNT="$(jq -r '.count' /tmp/results-map-quadrants-2025.json)"
EXPECTED_HASH="$(jq -r '.data[] | select(.example_id=="map_quadrants_2025_math_demo") | .expected_result_hash' /tmp/results-answer-key-2025.json)"
EXPECTED_COUNT="$(jq -r '.data[] | select(.example_id=="map_quadrants_2025_math_demo") | .expected_row_count' /tmp/results-answer-key-2025.json)"

test "$REPORT_HASH" = "$EXPECTED_HASH"
test "$REPORT_COUNT" = "$EXPECTED_COUNT"
printf 'verified map_quadrants_2025_math_demo rows=%s hash=%s\n' "$REPORT_COUNT" "$REPORT_HASH"
```

The comparison uses values from the surface. It does not compute the result hash.

## 5. Flip Only Norms Set

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/reports/map-quadrants?$COMMON_2020" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,hash:.meta.resultHash,rows:.data}'
```

This proves the same recipe runs under another norms set by changing one parameter.

## 6. Regenerate The Supporting Views

```sh
for report in retake-audit growth-over-time norms-isolation growth-breakdown group-growth-x student-progress-animation closed-loop-reconciliation; do
  curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/reports/$report?$COMMON_2025" \
    -H "Authorization: Bearer $RESULTS_TOKEN" \
    | jq --arg report "$report" '{report:$report,count,hash:.meta.resultHash,first:.data[0]}'
done
```

Use those rows directly in reports or apps. If a requested report cell is not returned by one of these endpoints, report a surface gap instead of calculating it locally.

## 7. Ask The Surface For MAP Translation And R90 Reference Rows

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/map-percentile-translations?subject=math&gradeLevel=7&termSeason=spring&normsSet=2025&translationDirection=percentile_to_rit&inputPercentile=99" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {input_percentile,output_rit,source_point_kind,calculator_version}}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/map-r90-norm-points?subject=math&gradeLevel=7&termSeason=spring&normsSet=2025" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {rit50_grade,rit90_grade,r90_rit,source_point_kind,calculator_version}}'
```

Use the returned percentile/RIT rows. Treat the Results R90 row as a legacy report fixture only; GOALS grade2RIT/R90 comes from the skill-seeded NWEAMAP master directly or through Analytics. Do not copy norms tables or R90 tables into the pack or client.

## 8. Read Results-Owned Student State

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/students/stu_timeback_10017/kc-state?subject=math&asOfDate=2026-06-03" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {kc_id,initial_mastery,current_retention,durable_mastery,fluency_state,next_due_at}}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/students/stu_timeback_10017/track-state?subject=math&asOfDate=2026-06-03" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {track_id,current_track_level_id,current_segment_id,status,placement_evidence}}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/next-task?studentId=stu_timeback_10017&subject=math&asOfDate=2026-06-03" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{task_type,task_ref_type,task_ref_id,reason,policy_version}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/students/stu_timeback_10017/xp-ledger" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {awarded_xp,award_reason,calculation_policy_ref}}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/content-effectiveness?subject=math" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {content_id,validated_by_count,failed_by_count,effectiveness_rate}}'
```

Use the returned state and derived-read rows directly. Do not blend the four KC states, rank next tasks, calculate XP, or increment content effectiveness.

## 9. Read Learning Report Time And XP Goal Evidence

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/reports/closed-loop-reconciliation?studentId=stu_timeback_10017&metricKind=minutes" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {metric_kind,activity_date,alpha_value,reconcile_status}}'

curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/students/stu_timeback_10017/growth-windows?subject=math&canonicalTermId=term_2025_26_spring&growthWindow=fall_to_spring&normsSet=2025" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {growth_x_target,on_track_for_growth_x_target,projected_gap,growth_x}}'
```

Use `alpha_value` as the time-commitment minutes value and use the returned growth-window fields as the surface-owned goal/progress projection evidence. If a user asks for remaining XP, hours-to-target, or target date fields not present in the response, report a Results surface gap instead of calculating them.

## 10. Read Transcript Answers Without Parsing Ed-Fi

```sh
curl -fsS "$RESULTS_BASE_URL/alpha/results/v1/transcript-results?studentId=stu_timeback_10017&courseId=course_algebra_1&canonicalTermId=term_2025_26_spring" \
  -H "Authorization: Bearer $RESULTS_TOKEN" \
  | jq '{count,first:.data[0] | {transcript_answer_kind,final_grade,earned_credits,answer_precedence}}'
```

Use the returned ordinary transcript answer row directly; source ids and `source_evidence` are deliberately absent. Do not inspect Ed-Fi source payloads or decide whether a CourseTranscript or Grade row wins; the surface owns that precedence. Audit workflows must use a separately supplied token with ordinary read authority plus the exact `results:audit` scope and append `includeSourceEvidence=true`.
