{
  "capability_id": "education.final_grade",
  "tool_id": "final-grade",
  "engine": "final-grade",
  "calculation_version": "1.1.1",
  "generated_at": "2026-09-16T22:03:43.767Z",
  "engine_build": "2026-09-10",
  "test_count": 26,
  "passed": 26,
  "failed": 0,
  "tests_summary": {
    "golden": {
      "total": 5,
      "passed": 5
    },
    "boundary": {
      "total": 12,
      "passed": 12
    },
    "property": {
      "total": 8,
      "passed": 8
    },
    "formula_crosscheck": {
      "total": 1,
      "passed": 1
    }
  },
  "engine_tested": true,
  "expert_reviewed": false,
  "internally_reviewed": false,
  "review_kind": null,
  "source_checked": true,
  "reviewed_by": null,
  "reviewer_role": null,
  "last_reviewed": null,
  "expert_review": {
    "status": "optional_not_performed",
    "reviewer": null,
    "scope": [
      "formula",
      "input semantics",
      "assumptions",
      "limitations",
      "sources",
      "tests"
    ],
    "note": "Domain expert review is optional under CVP (CVP-EXP-01). Absence does not block CVP Verified. See Review policy for supplemental domain assurance."
  },
  "internal_review": {
    "status": "not_applicable",
    "reviewer": null
  },
  "page": "https://www.calculatorx.com/calc/grade/final-grade",
  "api": "https://www.calculatorx.com/api/v1/calc/final-grade",
  "schema_input": "https://www.calculatorx.com/schemas/education.final_grade.input.json",
  "schema_output": "https://www.calculatorx.com/schemas/education.final_grade.output.json",
  "assumptions": [
    "Category weights are percentages that should total about 100% including remaining work.",
    "Need on final / Overall after final: Current must exclude the final. Do not enter a current grade that already counts the final as 0%.",
    "Weighted course: enter category grades and weights as they actually appear in the syllabus or LMS for completed work.",
    "No curve, drop-lowest, or extra credit unless you adjust inputs yourself."
  ],
  "limitations": [
    "Need on final / Overall: Current must exclude the final (pre-final grade). Do not enter an LMS current that already counts the final as 0%.",
    "Weighted: enter category grades and weights as they actually appear for completed work; remaining weight is optional.",
    "W is percent (40); w = W/100 is the fraction form. Do not mix W and w in one expression.",
    "Need on final with W = 0 → status invalid, code WEIGHT_REQUIRED (not a number).",
    "Points mode total ≤ 0 → TOTAL_POINTS_REQUIRED. Final points > total still computes and warns POINTS_EXCEED_TOTAL.",
    "Letter cutoffs / GPA points are a reference example, not part of the calculation model.",
    "Planning estimate only — not an official transcript. No curve, drop-lowest, or extra credit unless you adjust inputs.",
    "Engine aliases current/goal/W/finalScore/totalPoints are accepted at runtime; prefer share-URL field names in schemas."
  ],
  "boundary_conditions": [
    "Final weight must be > 0 for Need on final.",
    "Needed > 100% ⇒ goal unreachable; Needed = 0% ⇒ already secured boundary; Needed < 0% ⇒ goal already secured.",
    "W = 100% ⇒ Needed = Goal; W = 0% ⇒ validation error.",
    "Overall with W = 0% ⇒ Overall = Current; W = 100% ⇒ Overall = Final.",
    "Total points must be > 0 for Points → weight. Final points > total points is allowed but flagged."
  ],
  "sources": [
    {
      "title": "University of Chicago — Use Weighted Assignment Groups in Your Canvas Course",
      "section": "Total = Σ(category percentage × group weight); example: quizzes 20% + midterm 30% + final 40% + participation 10%",
      "url": "https://courses.uchicago.edu/2022/08/26/use-weighted-assignment-groups-in-your-canvas-course/",
      "supports": "Institutional statement of the weighted-category course grade as a linear combination of category averages",
      "kind": "reference",
      "accessed": "2026-08-18"
    },
    {
      "title": "Appalachian State University — Gradebook: Weighted Mean of Grades (Percentages)",
      "section": "Weighted mean of grades; unentered items are excluded and remaining weights are rescaled until those scores exist",
      "url": "https://confluence.appstate.edu/pages/viewpage.action?pageId=32473144",
      "supports": "Why Current grade should exclude the final, and why an LMS “current grade” may temporarily omit an ungraded final",
      "kind": "reference",
      "accessed": "2026-08-18"
    },
    {
      "title": "Weighted arithmetic mean (pre-final average and final exam weight)",
      "section": "Overall = Current×(100−W)/100 + Final×W/100, equivalently Current(1−w)+Final·w with w = W/100",
      "supports": "The algebraic identity used by Need on final and Overall after final, independent of any one school’s letter scale",
      "kind": "definition"
    }
  ],
  "methods": [],
  "fingerprint": "sha256:d0c84c4dfd54ae467be14367de1c0f3532748857b551ffe47175946d417c9479",
  "tests": [
    {
      "id": "need-85-90-40",
      "ok": true,
      "kind": "golden",
      "inputs": {
        "mode": "need",
        "currentInput": 85,
        "goalInput": 90,
        "weightInput": 40
      },
      "expect": {
        "value": 97.5,
        "reachability": "attainable"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 85,
        "goal": 90,
        "weight": 40,
        "remain": 60,
        "needed": 97.5,
        "value": 97.5,
        "unit": "%",
        "reachability": "attainable",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "need-70-80-50",
      "ok": true,
      "kind": "golden",
      "inputs": {
        "mode": "need",
        "currentInput": 70,
        "goalInput": 80,
        "weightInput": 50
      },
      "expect": {
        "value": 90,
        "reachability": "attainable"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 70,
        "goal": 80,
        "weight": 50,
        "remain": 50,
        "needed": 90,
        "value": 90,
        "unit": "%",
        "reachability": "attainable",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-w-100",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 70,
        "goalInput": 88,
        "weightInput": 100
      },
      "expect": {
        "value": 88,
        "reachability": "attainable"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 70,
        "goal": 88,
        "weight": 100,
        "remain": 0,
        "needed": 88,
        "value": 88,
        "unit": "%",
        "reachability": "attainable",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-w-0",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 85,
        "goalInput": 90,
        "weightInput": 0
      },
      "expectError": "WEIGHT_REQUIRED",
      "code": "WEIGHT_REQUIRED",
      "error": "Enter a final weight greater than 0."
    },
    {
      "id": "boundary-needed-100",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 80,
        "goalInput": 90,
        "weightInput": 50
      },
      "expect": {
        "value": 100,
        "reachability": "attainable"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 80,
        "goal": 90,
        "weight": 50,
        "remain": 50,
        "needed": 100,
        "value": 100,
        "unit": "%",
        "reachability": "attainable",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-unreachable",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 60,
        "goalInput": 95,
        "weightInput": 20
      },
      "expect": {
        "value": 235,
        "reachability": "unreachable"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 60,
        "goal": 95,
        "weight": 20,
        "remain": 80,
        "needed": 235,
        "value": 235,
        "unit": "%",
        "reachability": "unreachable",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-needed-0",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 100,
        "goalInput": 60,
        "weightInput": 40
      },
      "expect": {
        "value": 0,
        "reachability": "secured"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 100,
        "goal": 60,
        "weight": 40,
        "remain": 60,
        "needed": 0,
        "value": 0,
        "unit": "%",
        "reachability": "secured",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-needed-neg",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "need",
        "currentInput": 95,
        "goalInput": 70,
        "weightInput": 20
      },
      "expect": {
        "value": -30,
        "reachability": "secured"
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "need",
        "current": 95,
        "goal": 70,
        "weight": 20,
        "remain": 80,
        "needed": -30,
        "value": -30,
        "unit": "%",
        "reachability": "secured",
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "overall-85-92-40",
      "ok": true,
      "kind": "golden",
      "inputs": {
        "mode": "overall",
        "currentInput": 85,
        "finalScoreInput": 92,
        "weightInput": 40
      },
      "expect": {
        "value": 87.8
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "overall",
        "current": 85,
        "finalScore": 92,
        "weight": 40,
        "remain": 60,
        "overall": 87.8,
        "value": 87.8,
        "unit": "%",
        "reachability": null,
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-overall-w-0",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "overall",
        "currentInput": 85,
        "finalScoreInput": 92,
        "weightInput": 0
      },
      "expect": {
        "value": 85
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "overall",
        "current": 85,
        "finalScore": 92,
        "weight": 0,
        "remain": 100,
        "overall": 85,
        "value": 85,
        "unit": "%",
        "reachability": null,
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-overall-w-100",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "overall",
        "currentInput": 85,
        "finalScoreInput": 92,
        "weightInput": 100
      },
      "expect": {
        "value": 92
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "overall",
        "current": 85,
        "finalScore": 92,
        "weight": 100,
        "remain": 0,
        "overall": 92,
        "value": 92,
        "unit": "%",
        "reachability": null,
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "points-200-1000",
      "ok": true,
      "kind": "golden",
      "inputs": {
        "mode": "points",
        "totalPointsInput": 1000,
        "finalPointsInput": 200
      },
      "expect": {
        "value": 20
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "points",
        "total": 1000,
        "finalPts": 200,
        "weight": 20,
        "value": 20,
        "unit": "%",
        "reachability": null,
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-points-total-0",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "points",
        "totalPointsInput": 0,
        "finalPointsInput": 200
      },
      "expectError": "TOTAL_POINTS_REQUIRED",
      "code": "TOTAL_POINTS_REQUIRED",
      "error": "Enter total course points including the final."
    },
    {
      "id": "points-exceed-total",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "points",
        "totalPointsInput": 200,
        "finalPointsInput": 250
      },
      "expect": {
        "value": 125
      },
      "expectWarning": "POINTS_EXCEED_TOTAL",
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "points",
        "total": 200,
        "finalPts": 250,
        "weight": 125,
        "value": 125,
        "unit": "%",
        "reachability": null,
        "warnings": [
          {
            "code": "POINTS_EXCEED_TOTAL",
            "message": "Final points exceed course total."
          }
        ]
      },
      "tol": 1e-9
    },
    {
      "id": "xref-need-overall-identity",
      "ok": true,
      "kind": "formula_crosscheck",
      "inputs": {
        "mode": "overall",
        "currentInput": 85,
        "finalScoreInput": 97.5,
        "weightInput": 40
      },
      "expect": {
        "value": 90
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "overall",
        "current": 85,
        "finalScore": 97.5,
        "weight": 40,
        "remain": 60,
        "overall": 90,
        "value": 90,
        "unit": "%",
        "reachability": null,
        "warnings": []
      },
      "tol": 1e-9
    },
    {
      "id": "weighted-two-cats",
      "ok": true,
      "kind": "golden",
      "inputs": {
        "mode": "weighted",
        "categories": [
          {
            "grade": 80,
            "weight": 50
          },
          {
            "grade": 90,
            "weight": 50
          }
        ]
      },
      "expect": {
        "value": 85
      },
      "expectWarning": null,
      "actual": {
        "status": "ok",
        "code": null,
        "mode": "weighted",
        "counted": 2,
        "weightSum": 100,
        "weightedSum": 8500,
        "currentAvg": 85,
        "remain": 0,
        "goal": null,
        "unit": "%",
        "warnings": [],
        "needed": null,
        "value": 85,
        "reachability": null
      },
      "tol": 1e-9
    },
    {
      "id": "boundary-categories-empty",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "weighted",
        "categories": []
      },
      "expectError": "CATEGORIES_REQUIRED",
      "code": "CATEGORIES_REQUIRED",
      "error": "Add grades and weights for completed categories."
    },
    {
      "id": "boundary-overall-missing-final",
      "ok": true,
      "kind": "boundary",
      "inputs": {
        "mode": "overall",
        "currentInput": 85,
        "weightInput": 40
      },
      "expectError": "INPUT_REQUIRED",
      "code": "INPUT_REQUIRED",
      "error": "Enter the pre-final grade, final score, and final weight."
    },
    {
      "id": "property-deterministic",
      "ok": true,
      "kind": "property",
      "detail": "97.5",
      "expect": 97.5,
      "actual": 97.5
    },
    {
      "id": "property-w100-needed-eq-goal",
      "ok": true,
      "kind": "property",
      "detail": "88",
      "expect": 88,
      "actual": 88
    },
    {
      "id": "property-need-overall-roundtrip",
      "ok": true,
      "kind": "property",
      "detail": "90",
      "expect": 90,
      "actual": 90
    },
    {
      "id": "property-overall-w0",
      "ok": true,
      "kind": "property",
      "detail": "85",
      "expect": 85,
      "actual": 85
    },
    {
      "id": "property-overall-w100",
      "ok": true,
      "kind": "property",
      "detail": "92",
      "expect": 92,
      "actual": 92
    },
    {
      "id": "property-points-inverse",
      "ok": true,
      "kind": "property",
      "detail": "20",
      "expect": 20,
      "actual": 20
    },
    {
      "id": "property-monotonic-current",
      "ok": true,
      "kind": "property",
      "detail": "needed decreases as current increases",
      "expect": true,
      "actual": true
    },
    {
      "id": "property-Ww-identity",
      "ok": true,
      "kind": "property",
      "detail": "97.5",
      "expect": 97.5,
      "actual": 97.5
    }
  ],
  "tier": "engine_tested",
  "verification": {
    "tests": {
      "passed": 26,
      "total": 26,
      "golden": 5,
      "boundary": 12,
      "property": 8,
      "formula_crosscheck": 1
    },
    "contract_checks": {
      "passed": 4,
      "total": 4
    }
  },
  "evidence_core_generated_at": "2026-09-10T22:48:17.762Z",
  "rendered_at": "2026-09-16T22:03:43.767Z",
  "release_integrity": {
    "status": "verified",
    "scope": "workspace",
    "production_attestation_required": true,
    "calculation_version": "1.1.1",
    "artifacts": {
      "engine": "1.1.1",
      "page": "1.1.1",
      "capability": "1.1.1",
      "evidence": "1.1.1",
      "input_schema": "1.1.1",
      "output_schema": "1.1.1",
      "mcp_contract": "1.1.1"
    },
    "digests": {
      "input_schema_sha256": "548a9acb12e46491968636cf4991a6f7ab8a701719afbde49b6e02c3921c9df2",
      "output_schema_sha256": "2fa2caf68de0f94e8f23cae378eed36318bc3b0edbb0cdebcadfd2b07cd7e1ba",
      "evidence_sha256": "92d8cd734a00f3a55e5c4e760d7ab4067617415ec58353e7b59e151a95e05d59",
      "evidence_core_sha256": "92d8cd734a00f3a55e5c4e760d7ab4067617415ec58353e7b59e151a95e05d59",
      "capability_sha256": "2287b7eba1fea6801fa0e8d01dce485e4e74836f5b01ea4b5c91d48356640b75",
      "engine_sha256": "c8d4ccdbfeaf61d7b024d4e1babb0c2ba3b324c1b37bd0cb456a526d8d2b1bd1",
      "mcp_contract_sha256": "863098b311a7b17dc4b229a6302b90b3545b175f716e5d84772c7be8e9716b86"
    },
    "contract_checks": {
      "total": 4,
      "passed": 4,
      "failed": 0,
      "items": [
        {
          "id": "release-artifacts-aligned",
          "status": "pass",
          "detail": "1.1.1"
        },
        {
          "id": "schema-valid-input-executes",
          "status": "pass"
        },
        {
          "id": "engine-success-output-validates-schema",
          "status": "pass"
        },
        {
          "id": "schema-rejects-incomplete-input",
          "status": "pass"
        }
      ]
    },
    "report": "https://www.calculatorx.com/.well-known/calculatorx-release-integrity.json"
  }
}
