Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions loopx/capabilities/periodic_report/private_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ def validate_private_generation(folder: Path) -> dict[str, Any]:
# Rendering can improve after a window was frozen. Reconstruct only the
# exact prior presentation; never rewrite or regenerate it.
# Both candidates still require full bundle, source and body equality.
checked = build_periodic_report_generation_bundle(document=bundle["document"], artifacts=[
render_periodic_report_markdown(bundle["document"]),
render_periodic_report_html(bundle["document"], _legacy_masthead=True)])
if checked != bundle:
checked = build_periodic_report_generation_bundle(document=bundle["document"], artifacts=[
render_periodic_report_markdown(bundle["document"], _legacy_layout=True),
render_periodic_report_html(bundle["document"], _legacy_layout=True)])
Expand Down
13 changes: 10 additions & 3 deletions loopx/presentation/renderers/periodic_report_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ def _render_source_references(references: Mapping[str, int], labels: Mapping[str
.shell { width: min(1220px, calc(100% - 40px)); margin: 0 auto; padding: 40px 0 80px; }
.masthead { border-top: 8px solid var(--ink); border-bottom: 1.5px solid var(--ink);
padding: 27px 0 26px; }
.mast-grid { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px;
.mast-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 360px); gap: 28px;
align-items: end; }
.eyebrow { margin: 0 0 8px; color: var(--muted); font: 650 10px/1.4 var(--mono);
letter-spacing: .1em; text-transform: uppercase; }
Expand Down Expand Up @@ -663,13 +663,20 @@ def _render_source_references(references: Mapping[str, int], labels: Mapping[str


def render_periodic_report_html(document: Mapping[str, Any], *, _legacy_source_links: bool = False,
_legacy_layout: bool = False) -> dict[str, Any]:
_legacy_layout: bool = False,
_legacy_masthead: bool = False) -> dict[str, Any]:
"""Render one dense, self-contained report without changing its semantics."""

if document.get("schema_version") != DOCUMENT_SCHEMA:
raise ValueError(f"document must use {DOCUMENT_SCHEMA}")
validate_periodic_report_editorial(document)
_legacy_layout = _legacy_layout or _legacy_source_links
css = _CSS
if _legacy_masthead or _legacy_layout:
# Exact read-only reconstruction of already frozen presentations.
css = css.replace(
"grid-template-columns: minmax(0, 1fr) minmax(240px, 360px)",
"grid-template-columns: minmax(0, 1fr) auto", 1)
references = {} if _legacy_layout else _source_references(document)
sections = _items(document.get("sections"))
primary_sections = [
Expand Down Expand Up @@ -757,7 +764,7 @@ def render_periodic_report_html(document: Mapping[str, Any], *, _legacy_source_l
'<meta http-equiv="Content-Security-Policy" '
"content=\"default-src 'none'; style-src 'unsafe-inline'; "
"script-src 'unsafe-inline'; img-src data:\">"
f"<title>{title}</title><style>{_CSS}{_SOURCE_CSS if references else ''}</style></head><body>"
f"<title>{title}</title><style>{css}{_SOURCE_CSS if references else ''}</style></head><body>"
'<div class="shell" id="report-top" data-renderer="html_artifact_v0" '
'data-presentation="editorial_dense_v2">'
'<header class="masthead"><div class="mast-grid"><div>'
Expand Down
25 changes: 17 additions & 8 deletions tests/capabilities/test_periodic_report_private_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def host_codec_read_text(path: Path, *args, **kwargs):


@pytest.mark.parametrize("tamper", [None, "report", "html", "source", "response"])
@pytest.mark.parametrize("legacy_links", [False, True])
@pytest.mark.parametrize("legacy_links", [False, True, None])
def test_frozen_report_keeps_prior_presentations_across_renderer_upgrade(tmp_path, monkeypatch, tamper, legacy_links):
from loopx.presentation.renderers import periodic_report_html as html
from loopx.presentation.renderers import periodic_report_markdown as markdown
Expand All @@ -206,29 +206,38 @@ def previous_html_source(value, **_):

prior_markdown = markdown.render_periodic_report_markdown
prior_html = html.render_periodic_report_html
# Seed through the real freezer, retaining both shipped inline layouts.
# Seed through the real freezer, retaining all three shipped layouts.
# The old source rules remain independently specified, not inferred from
# the new link-eligibility helper or the validator's selected fallback.
with monkeypatch.context() as previous:
previous.setattr(markdown, "render_periodic_report_markdown", lambda document, **kwargs:
prior_markdown(document, **{**kwargs, "_legacy_layout": True}))
previous.setattr(html, "render_periodic_report_html", lambda document, **kwargs:
prior_html(document, **{**kwargs, "_legacy_layout": True}))
# Independently reproduce the shipped CSS. Its automatic side column
# predates bounded prose highlights in all three presentations.
previous.setattr(html, "_CSS", html._CSS.replace(
"grid-template-columns: minmax(0, 1fr) minmax(240px, 360px)",
"grid-template-columns: minmax(0, 1fr) auto", 1))
if legacy_links is not None:
previous.setattr(markdown, "render_periodic_report_markdown", lambda document, **kwargs:
prior_markdown(document, **{**kwargs, "_legacy_layout": True}))
previous.setattr(html, "render_periodic_report_html", lambda document, **kwargs:
prior_html(document, **{**kwargs, "_legacy_layout": True}))
if legacy_links:
previous.setattr(markdown, "_markdown_source", lambda value, labels, **_:
f"[{labels['source']}]({markdown._safe(value, maximum=500)})")
previous.setattr(html, "_safe_http_url", previous_html_source)
receipt = freeze_private_report(root=root, window=window, response=response)
original = {path.name: path.read_bytes() for path in folder.iterdir() if path.is_file()}
# Independent historical renderer oracles: parent of #7413 for old links,
# e20e4b684 for safe inline references. The input/window above is fixed.
# e20e4b684 for safe inline references, be1dc37a0 for indexed sources.
# The input/window above is fixed.
expected_text_digest = (
"509ff2e53bbce2f703049f1684e1a9f2048826ebb8c386891650b52841a1ed23"
if legacy_links else
"8d97d55e80f759e7eaadb73c5df93afea4d5cfbc071301a9726cb47ff37f9755"
if legacy_links is False else
"0041149af93d653431f5a70e0b98ad388462b1b93b81bc7a718a39f0b54dec8d"
)
assert hashlib.sha256(original["report.md"]).hexdigest() == expected_text_digest
assert ("[来源](sha256:" in original["report.md"].decode("utf-8")) is legacy_links
assert ("[来源](sha256:" in original["report.md"].decode("utf-8")) is bool(legacy_links)
assert "[来源](sha256:" not in markdown.render_periodic_report_markdown(
json.loads(original["generation-bundle.json"])["document"])["content"]

Expand Down
Loading