#!/usr/bin/env python3 """HTML layout helpers for the world-class evidence preflight report.""" from typing import Any from html_rendering import html_text SCRIPT_INTERFACE = "internal-module" SCRIPT_INTERFACE_REASON = "Imported by render_world_class_preflight.py to keep preflight HTML layout out of data assembly." def html_list(values: list[Any], empty: str) -> str: if not values: return f"
  • {html_text(empty)}
  • " return "".join(f"
  • {html_text(value)}
  • " for value in values) def render_html_commands(commands: dict[str, str]) -> str: return "".join( f"
  • {html_text(label.replace('_', ' '))}{html_text(command)}
  • " for label, command in commands.items() ) def render_html_prechecks(rows: list[dict[str, Any]]) -> str: if not rows: return "

    No prechecks listed.

    " return "".join( """
    {kind} {label}
    Current
    {actual}
    Status
    {status}
    Action
    {action}
    """.format( status=html_text(row.get("status", "")), kind=html_text(row.get("kind", "")), label=html_text(row.get("label", "")), actual=html_text(row.get("actual", "")), action=html_text(row.get("next_action", "")), ) for row in rows ) def render_html_source_checks(rows: list[dict[str, Any]]) -> str: if not rows: return "

    No source checks listed.

    " return "".join( """
    {field} {label}
    Current
    {actual}
    Expected
    {expected}
    Status
    {status}
    Action
    {action}
    """.format( status=html_text(row.get("status", "")), field=html_text(row.get("field", "")), label=html_text(row.get("label", "")), actual=html_text(row.get("actual", "")), expected=html_text(row.get("expected", "")), action=html_text(row.get("next_action", "")), ) for row in rows ) def render_html_repair_rows(rows: list[dict[str, Any]]) -> str: if not rows: return "

    No repair rows listed.

    " return "".join( """
    {repair_type} {target}
    Priority
    {priority}
    Phase
    {phase}
    Owner
    {owner}
    Status
    {status}
    Reason
    {reason}
    Action
    {action}
    Verify
    {verify}
    Evidence
    does not count as completion
    """.format( status=html_text(row.get("status", "")), repair_type=html_text(row.get("repair_type", "")), target=html_text(row.get("target", "")), priority=html_text(row.get("priority", "")), phase=html_text(row.get("phase", "")), owner=html_text(row.get("owner", "")), reason=html_text(row.get("blocking_reason", "")), action=html_text(row.get("next_action", "")), verify=html_text(row.get("verification_command", "")), ) for row in rows ) def render_html_phase_queue(rows: list[dict[str, Any]]) -> str: if not rows: return "

    No phase queue rows listed.

    " return "".join( """
    #{priority} · {status}

    {label}

    Phase
    {phase}
    Rows
    {blocked} / {total} blocked
    Owners
    {owners}
    Evidence
    {evidence}
    Next
    {action}
    Verify
    {verify}
    Counts
    does not count as completion
    """.format( status=html_text(row.get("status", "")), priority=html_text(row.get("priority", "")), label=html_text(row.get("label", "")), phase=html_text(row.get("phase", "")), blocked=html_text(row.get("blocked_count", 0)), total=html_text(row.get("row_count", 0)), owners=html_text(", ".join(str(owner) for owner in row.get("owners", [])) or "n/a"), evidence=html_text(", ".join(str(key) for key in row.get("evidence_keys", [])) or "n/a"), action=html_text(row.get("next_action", "")), verify=html_text(row.get("verification_command", "")), ) for row in rows ) def render_html_artifact_roles(contract: dict[str, Any]) -> str: cards = [] for role in contract.get("roles", []): role_name = str(role.get("role", "")) if role_name == "submission-ref": ready = f"{contract.get('submission_ref_ready_count', 0)}/{contract.get('submission_ref_total_count', 0)} ready" else: ready = ( f"{contract.get('supporting_evidence_ready_count', 0)}/" f"{contract.get('supporting_evidence_total_count', 0)} ready" ) cards.append( """
    {label}

    {role}

    {ready}

    {description}

    copy to artifact_refs: {copy}
    """.format( label=html_text(role.get("label", "")), role=html_text(role_name), ready=html_text(ready), description=html_text(role.get("description", "")), copy=html_text(str(role.get("copy_to_artifact_refs") is True).lower()), ) ) return "".join(cards) def render_html_item(item: dict[str, Any]) -> str: role_contract = item.get("submission_kit", {}).get("artifact_role_contract", {}) return f"""
    {html_text(item.get('category', ''))} · {html_text(item.get('status', ''))}

    {html_text(item.get('label', item.get('evidence_key', '')))}

    Evidence
    {html_text(item.get('evidence_key', ''))}
    Ledger
    {html_text(item.get('ledger_status', ''))}
    Intake
    {html_text(item.get('intake_readiness', ''))}
    Review
    {html_text(item.get('review_state', ''))}
    Draft
    {html_text(item.get('submission_path', ''))}

    Next Action

    {html_text(item.get('next_action', ''))}

    {html_text(item.get('commands', {}).get('prepare_submission', ''))} {html_text(item.get('commands', {}).get('prepare_prefilled_submission', ''))}

    Artifact Roles

    {render_html_artifact_roles(role_contract)}

    Prechecks

    {render_html_prechecks(item.get('prechecks', []))}

    Source Checks

    {render_html_source_checks(item.get('source_checklist', []))}

    Repair Rows

    {render_html_repair_rows(item.get('repair_checklist', []))}

    Runbook

    """ def render_html(report: dict[str, Any]) -> str: summary = report["summary"] stats = [ ("Decision", summary["decision"]), ("Pending", summary["pending_count"]), ("Ready", summary["collection_ready_count"]), ("Blocked", summary["collection_blocked_count"]), ("Source", f"{summary['source_pass_count']}/{summary['source_check_count']}"), ("Repairs", f"{summary.get('repair_blocked_count', 0)}/{summary.get('repair_checklist_count', 0)}"), ("Phases", f"{summary.get('phase_queue_blocked_count', 0)}/{summary.get('phase_queue_count', 0)}"), ] stat_html = "".join( f"
    {html_text(label)}{html_text(value)}
    " for label, value in stats ) role_contract = report["submissions"]["artifact_role_contract"] item_cards = "".join(render_html_item(item) for item in report.get("items", [])) phase_queue_html = render_html_phase_queue(report.get("phase_queue", [])) html = f""" World-Class Evidence Preflight
    Evidence Collection

    World-Class Evidence Preflight

    This operator view shows which external and human evidence is still blocked, which commands prepare editable submission drafts, and why preflight never counts as accepted evidence.

    {stat_html}

    Submission Kit

    Generate drafts only after real provider, human-review, native-permission, or native-client work exists. Drafts remain non-evidence until valid aggregate artifact refs and SHA-256 digests are supplied. Artifact prefill is convenience data only.

    • submissions directory: {html_text(report['submissions']['directory'])}
    • drafts count as evidence: {html_text(str(report['submissions']['drafts_count_as_evidence']).lower())}
    • artifact prefill counts as evidence: {html_text(str(report['submissions']['artifact_prefill_counts_as_evidence']).lower())}
    • preflight accepts evidence: {html_text(str(report['summary']['preflight_counts_as_evidence']).lower())}
    {render_html_artifact_roles(role_contract)}

    submission-ref rows are the paths expected in artifact_refs; supporting-evidence rows stay available for audit context.

    Phase Queue

    Repair rows are grouped into execution phases so operators can clear the first blocker before moving to later source collection. Phase queue rows remain procedural and never count as accepted evidence.

    {phase_queue_html}

    Evidence Queue

    {item_cards}

    Safety Boundary

    • Environment variables are displayed only as set or not-set; secret values are never printed.
    • Human-required and external-required states are operator work, not accepted evidence.
    • The world-class ledger remains the only source of truth for ready_to_claim_world_class.
    """ return "\n".join(line.rstrip() for line in html.splitlines()) + "\n"