diff --git a/normalize.py b/normalize.py
index f03c85d..f60bb4e 100644
--- a/normalize.py
+++ b/normalize.py
@@ -1,6 +1,32 @@
 def normalize_record(row):
-    """Return {name: stripped nonempty str, minutes: nonnegative int}; otherwise ValueError.
+    """
+    Return {name: stripped nonempty str, minutes: nonnegative int}; otherwise ValueError.
     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):
+        raise ValueError
+    
+    name = row.get('name')
+    minutes = row.get('minutes')
+    
+    if name is None or minutes is None:
+        raise ValueError
+    
+    name = name.strip()
+    if not name:
+        raise ValueError
+    
+    if isinstance(minutes, (int, float)):
+        if minutes < 0:
+            raise ValueError
+        minutes = int(minutes)
+    else:
+        if not isinstance(minutes, str):
+            raise ValueError
+        minutes = minutes.strip()
+        if not minutes.isdigit():
+            raise ValueError
+        minutes = int(minutes)
+    
+    return {"name": name, "minutes": minutes}
diff --git a/summary.py b/summary.py
index 1eb9d57..f91d029 100644
--- a/summary.py
+++ b/summary.py
@@ -1,7 +1,23 @@
 def summarize(records):
-    """Return normalized records count and sum of minutes by casefolded name.
+    """
+    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
+    if not records:
+        return {"count": 0, "minutes_by_name": {}}
+    
+    result = {"count": 0, "minutes_by_name": {}}
+    
+    for record in records:
+        try:
+            normalized = normalize_record(record)
+            name = normalized["name"].casefold()
+            result["count"] += 1
+            result["minutes_by_name"].setdefault(name, 0)
+            result["minutes_by_name"][name] += normalized["minutes"]
+        except ValueError:
+            raise ValueError
+    
+    return result
\ No newline at end of file
