#!/usr/bin/env python3 """Render Markdown and HTML artifacts for world-class submission kits.""" from typing import Any from html_rendering import html_text SCRIPT_INTERFACE = "internal-module" SCRIPT_INTERFACE_REASON = "Shared renderer for world-class submission kit Markdown and HTML artifacts." def render_readme(report: dict[str, Any]) -> str: commands = report["commands"] lines = [ "# World-Class Evidence Submission Kit", "", f"Generated at: `{report['generated_at']}`", "", "This kit contains editable drafts for human and external evidence packets. Drafts are not accepted evidence.", "", "## Workflow", "", "1. Run the real provider, human review, native permission, or native client telemetry work first.", "2. Edit the matching JSON draft with only aggregate artifact references and provenance metadata.", "3. Set `template_only` to `false` only after real evidence exists.", "4. Set attestation booleans truthfully; do not include credentials, raw prompts, raw outputs, transcripts, notes, or private user content.", "5. Validate the packet before asking the ledger reviewer to set `attestation.ledger_reviewer`, `attestation.ledger_reviewed_at`, and `attestation.ledger_reviewer_approved` truthfully.", "6. Optional artifact prefill only inserts SHA-256 digests for current local aggregate artifacts; it does not mark a draft as real evidence.", "", "## Commands", "", f"- validate intake: `{commands['validate_intake']}`", f"- review submission: `{commands['review_submission']}`", f"- refresh ledger: `{commands['refresh_ledger']}`", f"- guard public claims: `{commands['guard_claim']}`", "", "## Operator Handoff", "", "Follow these steps in order when handing the kit from operator to reviewer. Handoff rows are procedural and never count as completion evidence.", "", "| Step | Status | Command | Completion signal |", "| --- | --- | --- | --- |", ] for item in report.get("operator_handoff", []): command = item.get("command") or "manual" lines.append( f"| `{item['step_id']}` | `{item['status']}` | `{command}` | {item['completion_signal']} |" ) lines.extend( [ "", "## Phase Queue", "", "This queue groups repair rows by execution phase so operators can clear access, artifact, and source blockers in order. Queue rows are procedural guidance only.", "", "| Phase | Status | Rows | Owners | Next action | Verify |", "| --- | --- | ---: | --- | --- | --- |", ] ) phase_queue = report.get("phase_queue", []) if phase_queue: for item in phase_queue: owners = ", ".join(str(owner) for owner in item.get("owners", [])) or "n/a" lines.append( f"| `{item['phase']}` | `{item['status']}` | `{item['row_count']}` | {owners} | " f"{item['next_action']} | `{item['verification_command']}` |" ) else: lines.append("| `all` | `ready` | `0` | n/a | No phase blockers were generated. | `n/a` |") lines.extend( [ "", "## Drafts", "", "| Evidence | Draft | Status | Prefilled refs |", "| --- | --- | --- | ---: |", ] ) for item in report["files"]: lines.append( f"| `{item['evidence_key']}` | `{item['output_path']}` | `{item['status']}` | `{item.get('prefilled_artifact_ref_count', 0)}` |" ) lines.extend( [ "", "## Evidence Matrix", "", "This matrix combines draft, artifact, and source-check readiness into one operator action list. Matrix rows are guidance only; they do not count as completion evidence.", "", "| Evidence | Stage | Draft | Submission refs | Supporting assets | Source checks | Next action |", "| --- | --- | --- | ---: | ---: | ---: | --- |", ] ) for item in report.get("evidence_matrix", []): lines.append( f"| `{item['evidence_key']}` | `{item['stage']}` | `{item['draft_status']}` | " f"`{item.get('submission_ref_ready_count', 0)}/{item.get('submission_ref_total_count', 0)}` | " f"`{item.get('supporting_artifact_ready_count', 0)}/{item.get('supporting_artifact_total_count', 0)}` | " f"`{item['source_pass_count']}/{item['source_check_count']}` | {item['next_action']} |" ) lines.extend( [ "", "## Repair Checklist", "", "This checklist turns every draft, artifact, and source blocker into a concrete repair row. Repair rows are procedural guidance and do not count as completion evidence.", "", "| Evidence | Type | Target | Status | Next action |", "| --- | --- | --- | --- | --- |", ] ) repair_rows = report.get("repair_checklist", []) if repair_rows: for item in repair_rows: lines.append( f"| `{item['evidence_key']}` | `{item['repair_type']}` | `{item['target']}` | " f"`{item['status']}` | {item['next_action']} |" ) else: lines.append("| `all` | `none` | `n/a` | `ready` | No repair rows were generated. |") lines.extend(["", "## Execution Runbook", ""]) for item in report.get("evidence_items", []): must_collect = item.get("must_collect", {}) if isinstance(item.get("must_collect", {}), dict) else {} runbook = must_collect.get("runbook", []) lines.extend(["", f"### {item.get('label', item.get('evidence_key', 'Evidence'))}", ""]) if runbook: for step in runbook: lines.append(f"- `{step}`" if str(step).startswith("python3 ") or "=" in str(step) else f"- {step}") else: lines.append("- No source runbook listed.") lines.extend( [ "", "## Artifact Checklist", "", "Use these paths and SHA-256 digests when filling `artifact_refs`. Glob patterns are expanded into concrete files; submissions must reference concrete paths, not globs.", "", "| Evidence | Role | Path | Status | SHA-256 |", "| --- | --- | --- | --- | --- |", ] ) for item in report.get("artifact_checklist", []): digest = item.get("sha256") or "n/a" lines.append( f"| `{item['evidence_key']}` | `{item.get('artifact_role', 'supporting-evidence')}` | " f"`{item['path']}` | `{item['status']}` | `{digest}` |" ) lines.extend( [ "", "## Source Evidence Snapshot", "", "These checks explain why a draft is not ready for ledger acceptance yet. They mirror current aggregate reports and do not accept evidence by themselves.", "", "| Evidence | Check | Current | Expected | Status |", "| --- | --- | --- | --- | --- |", ] ) for item in report.get("source_checklist", []): lines.append( f"| `{item['evidence_key']}` | {item['label']} | `{item['actual']}` | `{item['expected']}` | `{item['status']}` |" ) lines.extend( [ "", "## Anti-Overclaim", "", "- This kit never marks ledger evidence as accepted.", "- Planned work, metadata fallback, pending review, and local command-runner output remain non-evidence.", "- A valid intake packet means ready for ledger review, not world-class completion.", ] ) return "\n".join(lines).rstrip() + "\n" def render_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_files(files: list[dict[str, Any]]) -> str: if not files: return '

    No submission drafts were requested.

    ' return "".join( """
    {status}

    {key}

    Template
    {template}
    Draft
    {output}
    Prefill
    {prefill} artifact refs
    {errors}
    """.format( status=html_text(item.get("status", "")), key=html_text(item.get("evidence_key", "")), template=html_text(item.get("template_path", "")), output=html_text(item.get("output_path", "")), prefill=html_text(item.get("prefilled_artifact_ref_count", 0)), errors=( '" if item.get("errors") else "" ), ) for item in files ) def render_html_artifact_checklist(items: list[dict[str, Any]]) -> str: if not items: return '

    No required artifacts were listed for the requested evidence.

    ' return "".join( """
    {key}

    {path}

    Pattern
    {pattern}
    Role
    {role}
    Status
    {status}
    SHA-256
    {sha}
    """.format( status=html_text(item.get("status", "")), key=html_text(item.get("evidence_key", "")), path=html_text(item.get("path", "")), pattern=html_text(item.get("source_pattern", "")), role=html_text(item.get("artifact_role", "supporting-evidence")), sha=html_text(item.get("sha256") or "n/a"), ) for item in items ) def render_html_source_checklist(items: list[dict[str, Any]]) -> str: if not items: return '

    No source checks were listed for the requested evidence.

    ' return "".join( """
    {key}

    {label}

    Field
    {field}
    Current
    {actual}
    Expected
    {expected}
    Action
    {action}
    """.format( status=html_text(item.get("status", "")), key=html_text(item.get("evidence_key", "")), label=html_text(item.get("label", "")), field=html_text(item.get("field", "")), actual=html_text(item.get("actual", "")), expected=html_text(item.get("expected", "")), action=html_text(item.get("next_action", "")), ) for item in items ) def render_html_matrix(items: list[dict[str, Any]]) -> str: if not items: return '

    No evidence matrix rows were generated.

    ' return "".join( """
    {stage}

    {key}

    Draft
    {draft}
    Submission refs
    {submission_ref_ready}/{submission_ref_total} ready
    Supporting assets
    {supporting_ready}/{supporting_total} ready
    Source
    {source_pass}/{source_total} pass
    Owner
    {owner}

    {action}

    """.format( stage=html_text(item.get("stage", "")), key=html_text(item.get("evidence_key", "")), draft=html_text(item.get("draft_status", "")), submission_ref_ready=html_text(item.get("submission_ref_ready_count", 0)), submission_ref_total=html_text(item.get("submission_ref_total_count", 0)), supporting_ready=html_text(item.get("supporting_artifact_ready_count", 0)), supporting_total=html_text(item.get("supporting_artifact_total_count", 0)), source_pass=html_text(item.get("source_pass_count", 0)), source_total=html_text(item.get("source_check_count", 0)), owner=html_text(item.get("owner", "")), action=html_text(item.get("next_action", "")), ) for item in items ) def render_html_repair_checklist(items: list[dict[str, Any]]) -> str: if not items: return '

    No repair rows were generated.

    ' return "".join( """
    {key} · {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(item.get("status", "")), key=html_text(item.get("evidence_key", "")), repair_type=html_text(item.get("repair_type", "")), target=html_text(item.get("target", "")), priority=html_text(item.get("priority", "")), phase=html_text(item.get("phase", "")), owner=html_text(item.get("owner", "")), reason=html_text(item.get("blocking_reason", "")), action=html_text(item.get("next_action", "")), verify=html_text(item.get("verification_command", "")), ) for item in items ) def render_html_phase_queue(items: list[dict[str, Any]]) -> str: if not items: return '

    No phase queue rows were generated.

    ' 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(item.get("status", "")), priority=html_text(item.get("priority", "")), label=html_text(item.get("label", "")), phase=html_text(item.get("phase", "")), blocked=html_text(item.get("blocked_count", 0)), total=html_text(item.get("row_count", 0)), owners=html_text(", ".join(str(owner) for owner in item.get("owners", [])) or "n/a"), evidence=html_text(", ".join(str(key) for key in item.get("evidence_keys", [])) or "n/a"), action=html_text(item.get("next_action", "")), verify=html_text(item.get("verification_command", "")), ) for item in items ) def render_html_handoff(items: list[dict[str, Any]]) -> str: if not items: return '

    No operator handoff steps were generated.

    ' return "".join( """
    {status}

    {label}

    Step
    {step}
    Command
    {command}
    Signal
    {signal}
    Evidence
    {counts}

    {blocking}

    """.format( status=html_text(item.get("status", "")), label=html_text(item.get("label", "")), step=html_text(item.get("step_id", "")), command=html_text(item.get("command") or "manual"), signal=html_text(item.get("completion_signal", "")), counts="does not count as completion" if item.get("counts_as_completion") is False else "review required", blocking=html_text(item.get("blocking_condition", "")), ) for item in items ) def render_html_item(item: dict[str, Any]) -> str: must_collect = item.get("must_collect", {}) if isinstance(item.get("must_collect", {}), dict) else {} runbook = must_collect.get("runbook", []) return f"""
    {html_text(item.get('category', ''))} · {html_text(item.get('readiness', ''))}

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

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

    Owner
    {html_text(item.get('owner', ''))}
    Evidence
    {html_text(item.get('evidence_key', ''))}
    Submission
    {html_text(item.get('submission_path', ''))}

    Execution Runbook

    Must Collect

      {render_html_list(must_collect.get('provenance_requirements', []), 'No provenance requirements listed.')}

    Pass Checks

      {render_html_list(must_collect.get('success_checks', []), 'No success checks listed.')}

    Privacy

      {render_html_list(must_collect.get('privacy_contract', []), 'No privacy contract listed.')}
    """ def render_html(report: dict[str, Any]) -> str: summary = report["summary"] artifact_ready = summary.get("artifact_ready_count", 0) artifact_total = summary.get("artifact_checklist_count", 0) submission_ref_ready = summary.get("submission_ref_ready_count", 0) submission_ref_total = summary.get("submission_ref_count", 0) stats = [ ("Requested", summary["requested_count"]), ("Written", summary["written_count"]), ("Existing", summary["existing_count"]), ("Skipped", summary["skipped_count"]), ("Submit refs", f"{submission_ref_ready}/{submission_ref_total}"), ("Support", f"{artifact_ready - submission_ref_ready}/{artifact_total - submission_ref_total}"), ("Prefilled", summary.get("artifact_ref_prefill_count", 0)), ] stat_html = "".join( f"
    {html_text(label)}{html_text(value)}
    " for label, value in stats ) evidence_html = "".join(render_html_item(item) for item in report.get("evidence_items", [])) matrix_html = render_html_matrix(report.get("evidence_matrix", [])) repair_html = render_html_repair_checklist(report.get("repair_checklist", [])) phase_queue_html = render_html_phase_queue(report.get("phase_queue", [])) handoff_html = render_html_handoff(report.get("operator_handoff", [])) artifact_html = render_html_artifact_checklist(report.get("artifact_checklist", [])) source_html = render_html_source_checklist(report.get("source_checklist", [])) return f""" World-Class Evidence Submission Kit
    Evidence Intake

    World-Class Evidence Submission Kit

    Use this cockpit to prepare human and external evidence packets. Drafts are not accepted evidence, artifact prefill only inserts local SHA-256 digests, and this page never changes the ledger result.

    {stat_html}

    Workflow

    1. Run the real provider, human review, native permission, or native client telemetry work first.
    2. Edit the matching JSON draft with aggregate artifact references and provenance metadata.
    3. Set template_only to false only after real evidence exists.
    4. Use prefilled SHA-256 values as convenience data, not evidence acceptance.
    5. Validate intake, ask the ledger reviewer to approve explicitly, refresh the ledger, then guard public claims.

    Operator Handoff

    These ordered steps make the operator-to-reviewer handoff auditable. They are procedural guardrails and never count as world-class evidence.

    {handoff_html}

    Phase Queue

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

    {phase_queue_html}

    Evidence Matrix

    The matrix separates submission artifact_refs from supporting assets, then combines draft status, source checks, and the next operator action. It is guidance only and never counts as accepted evidence.

    {matrix_html}

    Repair Checklist

    Each row names one concrete blocker and the next action required before ledger review. This checklist does not count as completion evidence.

    {repair_html}

    Drafts

    {render_html_files(report['files'])}

    Artifact Checklist

    Rows marked submission-ref are the paths expected in artifact_refs. Supporting-evidence rows help reviewers audit the packet but do not all need to be copied into the submission. Glob patterns are expanded for operator convenience only.

    {artifact_html}

    Source Evidence Snapshot

    This section shows current aggregate source checks. It explains remaining blockers without changing the ledger.

    {source_html}

    Evidence Requirements

    {evidence_html}

    Safety Boundary

    • Drafts never count as accepted ledger evidence.
    • Valid intake means ready for ledger review, not world-class completion.
    • Do not include credentials, raw prompts, raw outputs, transcripts, notes, or private user content.
    """