diff --git a/normalize.py b/normalize.py
index f03c85d..26eaf4a 100644
--- a/normalize.py
+++ b/normalize.py
@@ -3,4 +3,27 @@ def normalize_record(row):
     Accept minutes as int or decimal digit string (strip whitespace); reject bool and float.
     Do not mutate the input. Missing name/minutes or nondict input is invalid.
     """
-    raise NotImplementedError
+    if not isinstance(row, dict) or "name" not in row or "minutes" not in row:
+        raise ValueError("record must be a dictionary with name and minutes")
+
+    name = row["name"]
+    if not isinstance(name, str):
+        raise ValueError("name must be a nonempty string")
+    name = name.strip()
+    if not name:
+        raise ValueError("name must be a nonempty string")
+
+    minutes = row["minutes"]
+    if isinstance(minutes, bool):
+        raise ValueError("minutes must be a nonnegative integer")
+    if isinstance(minutes, str):
+        minutes = minutes.strip()
+        if not minutes or not minutes.isdecimal():
+            raise ValueError("minutes must be a nonnegative integer")
+        minutes = int(minutes)
+    elif not isinstance(minutes, int):
+        raise ValueError("minutes must be a nonnegative integer")
+
+    if minutes < 0:
+        raise ValueError("minutes must be a nonnegative integer")
+    return {"name": name, "minutes": minutes}
diff --git a/summary.py b/summary.py
index 1eb9d57..e9a0bfc 100644
--- a/summary.py
+++ b/summary.py
@@ -1,7 +1,17 @@
+from normalize import normalize_record
+
+
 def summarize(records):
     """Return normalized records count and sum of minutes by casefolded name.
     Format: {"count": n, "minutes_by_name": {name: total}}. Use normalize_record.
     Empty input returns count 0 and empty map. Invalid record must raise ValueError.
     Do not mutate inputs.
     """
-    raise NotImplementedError
+    count = 0
+    minutes_by_name = {}
+    for record in records:
+        normalized = normalize_record(record)
+        key = normalized["name"].casefold()
+        count += 1
+        minutes_by_name[key] = minutes_by_name.get(key, 0) + normalized["minutes"]
+    return {"count": count, "minutes_by_name": minutes_by_name}
