Class: AISpec::Core::Reporters::HTML
- Defined in:
- lib/aispec/core/reporters/html.rb
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
Methods inherited from Base
Constructor Details
This class inherits a constructor from AISpec::Core::Reporters::Base
Instance Method Details
#render ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/aispec/core/reporters/html.rb', line 7 def render contract = results[:contract] stats = results[:statistics] summary = stats.summary html = <<~HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AISpec Contract Verification Report - #{contract.name}</title> <style> :root { --bg: #0f172a; --card-bg: #1e293b; --text: #f8fafc; --text-muted: #94a3b8; --accent: #6366f1; --success: #22c55e; --danger: #ef4444; --border: #334155; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background-color: var(--bg); color: var(--text); margin: 0; padding: 2rem; } .container { max-width: 1100px; margin: 0 auto; } header { margin-bottom: 2rem; border-bottom: 1px solid var(--border); padding-bottom: 1rem; } h1 { margin: 0 0 0.5rem 0; font-size: 2rem; } .subtitle { color: var(--text-muted); font-size: 1.1rem; } .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; margin-bottom: 2rem; } .card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem; } .card-title { color: var(--text-muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; } .card-value { font-size: 1.8rem; font-weight: 700; margin-top: 0.5rem; } .badge-pass { color: var(--success); } .badge-fail { color: var(--danger); } section { background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem; } h2 { margin-top: 0; font-size: 1.3rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; } table { width: 100%; border-collapse: collapse; margin-top: 1rem; } th, td { text-align: left; padding: 0.75rem; border-bottom: 1px solid var(--border); } th { color: var(--text-muted); font-weight: 600; font-size: 0.9rem; } pre { background: #090d16; padding: 1rem; border-radius: 8px; overflow-x: auto; font-size: 0.9rem; color: #e2e8f0; } </style> </head> <body> <div class="container"> <header> <h1>AISpec Behavioral Contract Report</h1> <div class="subtitle">Contract: <strong>#{contract.name}</strong> | Provider: <strong>#{results[:provider_name]}</strong> | Model: <strong>#{results[:model]}</strong></div> </header> <div class="grid"> <div class="card"> <div class="card-title">Behavior Score</div> <div class="card-value #{summary[:success_rate] >= 90 ? 'badge-pass' : 'badge-fail'}">#{summary[:success_rate]}%</div> <div style="font-size:0.8rem; color:var(--text-muted);">CI: ±#{summary[:confidence_interval]}%</div> </div> <div class="card"> <div class="card-title">Assertions</div> <div class="card-value">#{summary[:passed_assertions]} / #{summary[:total_assertions]}</div> </div> <div class="card"> <div class="card-title">Mean Latency</div> <div class="card-value">#{summary[:mean_latency]} ms</div> </div> <div class="card"> <div class="card-title">Total Cost</div> <div class="card-value">$#{sprintf('%.4f', summary[:total_cost])}</div> </div> <div class="card"> <div class="card-title">Recommendation</div> <div class="card-value" style="font-size:1.2rem; margin-top:0.8rem;">#{summary[:recommendation]}</div> </div> </div> <section> <h2>Summary & Analysis</h2> <p><strong>Average Judge Score:</strong> #{summary[:average_judge_score] || 'N/A'}</p> <p><strong>Variance:</strong> #{summary[:variance]}</p> </section> <section> <h2>Test Runs & Prompt Details</h2> #{render_runs_table} </section> </div> </body> </html> HTML output_io.puts html html end |