diff --git a/app/src/components/AuditPanel.tsx b/app/src/components/AuditPanel.tsx
index fc4d021..e7f830a 100644
--- a/app/src/components/AuditPanel.tsx
+++ b/app/src/components/AuditPanel.tsx
@@ -85,12 +85,16 @@ export default function AuditPanel() {
config,
scenarios,
(p) => {
- setProgress(p);
+ if (typeof p === 'number') setProgress(p);
},
controller.signal
);
setReport(reportResult);
setStatus('done');
+
+ // Auto-download MD
+ import('@/lib/audit/export-audit-md').then(m => m.downloadAuditMarkdown(reportResult));
+
} catch (e) {
if (e instanceof Error && e.message.includes('Abortado')) {
setStatus('idle');
@@ -186,10 +190,16 @@ export default function AuditPanel() {
)}
{status === 'done' && report && (
-
+ <>
+
+
+ >
)}
diff --git a/app/src/lib/audit/export-audit-md.ts b/app/src/lib/audit/export-audit-md.ts
new file mode 100644
index 0000000..cdf52c8
--- /dev/null
+++ b/app/src/lib/audit/export-audit-md.ts
@@ -0,0 +1,56 @@
+import type { AuditReport } from './types';
+
+export function generateAuditMarkdown(report: AuditReport): string {
+ let md = `# Relatório de Auditoria — BrainWind\n\n`;
+ md += `**Provedor:** ${report.provider} (${report.model})\n`;
+ md += `**Data:** ${new Date(report.timestamp).toLocaleString('pt-BR')}\n\n`;
+
+ md += `## Resumo Geral\n`;
+ md += `- **Total de Cenários:** ${report.totalScenarios}\n`;
+ md += `- **PASS:** ${report.totalPassed} ✅\n`;
+ md += `- **WARN:** ${report.totalWarnings} ⚠️\n`;
+ md += `- **FAIL:** ${report.totalFailed} ❌\n\n`;
+
+ for (const mod of report.modules) {
+ md += `## Módulo: ${mod.moduleLabel}\n`;
+ md += `**Total:** ${mod.totalScenarios} | **PASS:** ${mod.passed} | **WARN:** ${mod.warnings} | **FAIL:** ${mod.failed}\n\n`;
+
+ for (const sc of mod.scenarios) {
+ const icon = sc.verdict === 'PASS' ? '✅' : sc.verdict === 'WARN' ? '⚠️' : '❌';
+ md += `### ${icon} Cenário: ${sc.scenarioId}\n`;
+ md += `**Veredito:** ${sc.verdict} — *${sc.summary}*\n\n`;
+
+ if (sc.llmNotes) {
+ md += `**Observações da IA:** ${sc.llmNotes}\n\n`;
+ }
+
+ md += `**Raciocínio Matemático (Chain of Thought):**\n`;
+ const calcSteps = sc.calculation_steps || 'Sem raciocínio fornecido pela IA.';
+ md += `> ${calcSteps.split('\n').join('\n> ')}\n\n`;
+
+ md += `**Verificações Individuais:**\n`;
+ for (const chk of sc.checks) {
+ const chkIcon = chk.status === 'PASS' ? '✅' : chk.status === 'WARN' ? '⚠️' : '❌';
+ md += `- ${chkIcon} **${chk.name}:** Calculado IA = \`${chk.expected}\` | App = \`${chk.actual}\`\n`;
+ if (chk.explanation) {
+ md += ` - *Nota:* ${chk.explanation}\n`;
+ }
+ }
+ md += `\n---\n\n`;
+ }
+ }
+
+ return md;
+}
+
+export function downloadAuditMarkdown(report: AuditReport) {
+ const md = generateAuditMarkdown(report);
+ const blob = new Blob([md], { type: 'text/markdown;charset=utf-8' });
+ const url = URL.createObjectURL(blob);
+ const link = document.createElement('a');
+ link.setAttribute('href', url);
+ link.setAttribute('download', `auditoria-${report.id}.md`);
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+}
diff --git a/app/src/lib/audit/export-audit-pdf.tsx b/app/src/lib/audit/export-audit-pdf.tsx
index 3f13108..51e50da 100644
--- a/app/src/lib/audit/export-audit-pdf.tsx
+++ b/app/src/lib/audit/export-audit-pdf.tsx
@@ -101,7 +101,7 @@ function AuditReportDocument({ report }: ReportPDFProps) {
{report.modules.map((mod: ModuleAuditResult) => (
-
+
{mod.moduleLabel} — {mod.passed}/{mod.totalScenarios} (W:{mod.warnings} F:{mod.failed})