renderAuditReport builds and renders the audit report from a fully-populated processedRun. It is called both when serving from a cached run summary and after a fresh processing pass, ensuring that the two paths produce identical output.
(ctx context.Context, processedRun ProcessedRun, metrics LogMetrics, mcpToolUsage *MCPToolUsageData, opts AuditOptions)
| 819 | // It is called both when serving from a cached run summary and after a fresh processing pass, |
| 820 | // ensuring that the two paths produce identical output. |
| 821 | func renderAuditReport(ctx context.Context, processedRun ProcessedRun, metrics LogMetrics, mcpToolUsage *MCPToolUsageData, opts AuditOptions) error { |
| 822 | runID := processedRun.Run.DatabaseID |
| 823 | runOutputDir := opts.OutputDir |
| 824 | processedRun.Run.SafeItemsCount = len(extractCreatedItemsFromManifest(runOutputDir)) |
| 825 | auditData := buildRenderedAuditData(ctx, processedRun, metrics, mcpToolUsage, runOutputDir, opts) |
| 826 | if err := renderAuditOutput(auditData, runOutputDir, opts.JSONOutput, opts.Verbose); err != nil { |
| 827 | return err |
| 828 | } |
| 829 | renderAuditGatewayMetrics(runOutputDir, opts.Verbose) |
| 830 | renderAuditUnifiedTimeline(runOutputDir, opts.Verbose) |
| 831 | parseAuditLogsIfRequested(runID, runOutputDir, opts) |
| 832 | renderAuditCompletion(runOutputDir, opts.JSONOutput) |
| 833 | return nil |
| 834 | } |
| 835 | |
| 836 | func buildRenderedAuditData(ctx context.Context, processedRun ProcessedRun, metrics LogMetrics, mcpToolUsage *MCPToolUsageData, runOutputDir string, opts AuditOptions) AuditData { |
| 837 | currentCreatedItems := extractCreatedItemsFromManifest(runOutputDir) |