diff --git a/services/api-server/src/api_server/html5.py b/services/api-server/src/api_server/html5.py
index e0eac52..2c3af4a 100644
--- a/services/api-server/src/api_server/html5.py
+++ b/services/api-server/src/api_server/html5.py
@@ -978,6 +978,7 @@ def render_html5_authoring_change_detail(project_id: str, preview: object | None
{escape(original_version_id)} -> {escape(rollback_version_id)}
{escape(change_id)}
+ {_authoring_detail_summary(diff, checks, apply_available)}
{check_rows}
{diff_rows}
{apply_form}
@@ -1718,6 +1719,23 @@ def _authoring_changes_summary(changes: Iterable[object]) -> str:
"""
+def _authoring_detail_summary(diff: Iterable[object], checks: Iterable[object], apply_available: bool) -> str:
+ diff_list = list(diff)
+ check_list = list(checks)
+ diff_kinds = Counter(str(getattr(line, "kind", "") or "CHANGE") for line in diff_list)
+ check_statuses = Counter(str(getattr(check, "status", "") or "UNKNOWN") for check in check_list)
+ added = sum(1 for line in diff_list if str(getattr(line, "kind", "")) == "ADD")
+ removed = sum(1 for line in diff_list if str(getattr(line, "kind", "")) == "REMOVE")
+ diff_text = ", ".join(f"{name}: {count}" for name, count in sorted(diff_kinds.items())) or "empty diff"
+ check_text = ", ".join(f"{name}: {count}" for name, count in sorted(check_statuses.items())) or "no checks"
+ state = "rollback ready" if apply_available else "rollback blocked"
+ return f"""
+
+ {escape(state)} · {escape(str(len(diff_list)))} diff lines · +{escape(str(added))} / -{escape(str(removed))} · {escape(diff_text)} · {escape(check_text)}
+
+ """
+
+
def _named_node_item(label: str, node: object) -> str:
name = getattr(node, "qualified_name", None) or getattr(node, "name", "")
kind = getattr(node, "kind", label)
diff --git a/services/api-server/tests/test_api.py b/services/api-server/tests/test_api.py
index 0bb2622..45f6509 100644
--- a/services/api-server/tests/test_api.py
+++ b/services/api-server/tests/test_api.py
@@ -2700,6 +2700,9 @@ def test_authoring_context_and_completion_preview(tmp_path: Path):
assert html5_detail.status_code == 200
assert "text/html" in html5_detail.headers["content-type"]
assert "data-html5-authoring-detail" in html5_detail.text
+ assert "data-html5-authoring-detail-summary" in html5_detail.text
+ assert "rollback ready" in html5_detail.text
+ assert "diff lines" in html5_detail.text
assert "Rollback preview" in html5_detail.text
assert "data-html5-authoring-rollback-form" in html5_detail.text
assert f'hx-post="/html5/projects/{project_id}/authoring/changes/{apply_payload["change_id"]}/apply-rollback"' in html5_detail.text