"""Offline HTML reading view of the validated v2.9 record; no model pass."""
import re
from html import escape
from pathlib import Path
from brief_sections import CLOSING, PP_CLASSES
from chat_result import ASSESSMENTS, READING_GUIDE, overview, review_limits
ASSETS = Path(__file__).resolve().parent.parent / "assets"
GROUPS = (
("breaks_position", "Problems with the position"),
("internal_defect", "Contradictions to correct"),
("proof_gap", "Evidence still needed"),
("context", "Practical points and qualifications"),
("defeated", "Objections the documents answer"),
("weakens_route", "Arguments that fail without changing the conclusion"),
)
def text(value):
"""Treat source and model text as text, allowing only bold emphasis."""
return re.sub(r"\*\*([^*\n]+)\*\*", r"\1", escape(str(value)))
def paragraph(value, label=None):
prefix = f"{escape(label)}: " if label else ""
return f"
{prefix}{text(value)}
"
def source(data, filename, root):
meta = data["sources"][filename]
label = escape(meta["name"])
if meta.get("date"):
label += ", " + escape(meta["date"])
if root is not None:
base = Path(root).resolve()
path = (base / filename).resolve()
if (
not Path(filename).is_absolute()
and path.is_relative_to(base)
and path.is_file()
):
return f'{label}'
return label
def passages(data, anchors, root):
return "".join(
''
+ source(data, a["source"], root)
+ " โ "
+ escape(a["locator"])
+ "
"
+ escape(a["quote"])
+ "
"
for a in anchors
)
def finding(data, item, number, root):
cls = item["classification"]
opened = " open" if cls in PP_CLASSES else ""
parts = [
f'',
f'{number:02}',
f'{text(item["title"])}',
f'{ASSESSMENTS[cls]}',
'
',
paragraph(item["statement"]),
]
if cls in PP_CLASSES:
parts.append(paragraph(item["hits"], "Affects"))
parts.append(passages(data, item["anchors"], root))
answer = (
"Why this objection is answered"
if cls == "defeated"
else "Why the conclusion remains supported"
)
for field, label in (
("test_applied", "Assessment"),
("dispositive_anchor_note", answer),
("flip_statement", "Consequence if accepted"),
("defect_statement", "Consequence if accepted"),
("survives", "What remains supported"),
("smallest_change", "What would change this result"),
("what_would_close", "Evidence needed"),
("next_step", "Next action"),
):
if item.get(field):
parts.append(paragraph(item[field], label))
parts.append("
")
return "".join(parts)
def render_html(data, source_root=None):
brief = data["brief"]
findings = data["findings"]
# Use the same verdict wording as the complete chat reading view.
verdict = overview(data, findings)[2].strip("*")
parts = [
'
PRESSURETEST ยท FOR LAWYER REVIEW
',
f"
{text(brief['position_name'])}
",
paragraph(brief["run_date"]),
"",
'
Summary
',
paragraph(verdict, "Assessment"),
paragraph(brief["summary"]),
paragraph(READING_GUIDE, "How to read this review"),
]
if data["verdict"] == "incomplete":
parts.append(paragraph(data["incomplete_reason"], "Unfinished review"))
for field, label in (
("established", "What is established"),
("follows", "What currently follows"),
):
if brief.get(field):
parts.append(paragraph(brief[field], label))
parts += ["
Position tested
"]
for position in data["positions"]:
parts.append(paragraph(position["conclusion"], position["owner"]))
ordered = [f for cls, _ in GROUPS for f in findings if f["classification"] == cls]
attention = [
(n, f)
for n, f in enumerate(ordered, 1)
if f["classification"] not in ("defeated", "weakens_route")
]
if attention:
parts += ['
',
]
number = 0
for cls, title in GROUPS:
if cls == "defeated":
route_title = (
"Why the conclusion remains supported"
if data["verdict"] == "position_holds"
else "The strongest argument supporting the position"
)
parts += [
f"
{route_title}
",
paragraph(data["strongest_route"]["summary"]),
passages(data, data["strongest_route"]["anchors"], source_root),
"",
]
group = [f for f in findings if f["classification"] == cls]
if group:
parts.append(f'
{title}
')
for item in group:
number += 1
parts.append(finding(data, item, number, source_root))
parts.append("")
parts.append('')
for value in brief.get("context_items") or []:
parts.append(paragraph(value))
for line in review_limits(data):
if line.startswith("## "):
parts.append(f"
")
for filename in data["coverage"]["selected"]:
state = next(
k
for k in ("reviewed", "parked", "excluded", "unreadable")
if filename in data["coverage"][k]
)
parts.append(
f"
{source(data, filename, source_root)} โ "
f"{'unread' if state == 'parked' else state}
"
)
parts += ["
"]
template = (ASSETS / "report-template.html").read_text(encoding="utf-8")
replacements = {
"TITLE": escape(brief["position_name"]),
"CONTENT": "\n".join(parts),
}
return re.sub(r"\{\{(TITLE|CONTENT)\}\}", lambda m: replacements[m[1]], template)
def render_handoff(data):
"""Short native-chat handoff; the host appends the real artifact link."""
parts = overview(data, data["findings"])
parts += [
"The full HTML report contains every finding, supporting passage, "
"next action and review limit. Open the report linked below.",
"",
]
return "\n".join(parts).rstrip() + "\n"