ITNovaML/PCAgentinAI
0
1# ============================================================2# app.py — Integration snippets for Agent 6 (AXIOM Audit Agent)3# Add these to your existing app.py4# ============================================================5 6# ── 1. Import at top of app.py ───────────────────────────────7from agent6_audit import run_audit_agent, get_audit_for_submission8 9 10# ── 2. Call AXIOM at end of pipeline (after NOVA) ───────────11# In your existing pipeline route (wherever NOVA runs), add:12 13def run_full_pipeline(submission_id: int) -> dict:14 """15 Example: call this at the end of your existing pipeline function.16 Replace with your actual pipeline call.17 """18 # ... your existing agent calls (AURA, TERRA, KARMA, AURUM, NOVA) ...19 20 # ✅ ADD THIS at the very end, after NOVA issues/declines:21 audit_result = run_audit_agent(submission_id)22 23 return {24 # ... your existing pipeline result dict ...25 "audit": audit_result,26 }27 28 29# ── 3. Flask API route — GET audit for a submission ──────────30from flask import jsonify, request31 32@app.route("/audit/<int:submission_id>", methods=["GET"])33def get_audit(submission_id):34 """35 Returns the audit record for a given submission.36 Called by the UI audit panel.37 GET /audit/12338 """39 record = get_audit_for_submission(submission_id)40 if not record:41 # Run it on demand if not yet generated42 record = run_audit_agent(submission_id)43 return jsonify(record)44 45 46@app.route("/audit/run/<int:submission_id>", methods=["POST"])47def trigger_audit(submission_id):48 """49 Manually trigger audit for a submission (useful for backfill).50 POST /audit/run/12351 """52 result = run_audit_agent(submission_id)53 return jsonify(result)54 55 56# ============================================================57# HTML AUDIT PANEL — Add this to your existing policy detail58# page or results screen in your HTML/Jinja templates59# ============================================================60AUDIT_PANEL_HTML = """61<!-- ── AXIOM AUDIT PANEL ─────────────────────────────────── -->62<div id="auditPanel" style="63 background: #0a1628;64 border: 1px solid rgba(0,212,255,0.2);65 border-radius: 4px;66 padding: 1.5rem 2rem;67 margin-top: 2rem;68 font-family: 'DM Mono', monospace;69">70 <div style="display:flex; align-items:center; gap:0.8rem; margin-bottom:1.2rem;">71 <span style="font-size:1.2rem;">🔍</span>72 <div>73 <div style="font-weight:700; font-size:0.9rem; color:#f0f6ff; letter-spacing:0.05em;">74 AXIOM — Audit Agent75 </div>76 <div style="font-size:0.65rem; color:#7a9ab8; letter-spacing:0.1em; text-transform:uppercase;">77 Agent 6 · Decision Audit · Gold Layer78 </div>79 </div>80 <div id="auditDecisionBadge" style="81 margin-left:auto;82 font-size:0.7rem;83 font-weight:700;84 letter-spacing:0.12em;85 text-transform:uppercase;86 padding:0.3rem 0.9rem;87 border:1px solid;88 border-radius:2px;89 ">Loading...</div>90 </div>91 92 <!-- Overall summary -->93 <div id="auditSummaryText" style="94 font-size:0.82rem;95 color:#a8c0d8;96 line-height:1.7;97 background:rgba(255,255,255,0.03);98 border-left:3px solid #00d4ff;99 padding:0.8rem 1rem;100 margin-bottom:1.2rem;101 ">Loading audit summary...</div>102 103 <!-- Audit score -->104 <div style="display:flex; align-items:center; gap:0.8rem; margin-bottom:1.2rem;">105 <div style="font-size:0.65rem; color:#7a9ab8; text-transform:uppercase; letter-spacing:0.1em;">106 Audit Confidence Score107 </div>108 <div style="flex:1; height:6px; background:rgba(255,255,255,0.08); border-radius:3px; overflow:hidden;">109 <div id="auditScoreBar" style="height:100%; width:0%; background:#00d4ff; transition:width 1s ease; border-radius:3px;"></div>110 </div>111 <div id="auditScoreVal" style="font-size:0.75rem; font-weight:700; color:#00d4ff; width:36px;">0%</div>112 </div>113 114 <!-- Decision factors table -->115 <div style="font-size:0.65rem; color:#7a9ab8; text-transform:uppercase; letter-spacing:0.1em; margin-bottom:0.6rem;">116 Agent Decision Factors117 </div>118 <div id="auditFactors" style="display:flex; flex-direction:column; gap:0.5rem;"></div>119 120 <!-- Decline reasons (only shown if declined) -->121 <div id="auditDeclineReasons" style="display:none; margin-top:1rem;">122 <div style="font-size:0.65rem; color:#ef4444; text-transform:uppercase; letter-spacing:0.1em; margin-bottom:0.5rem;">123 Decline Reasons124 </div>125 <div id="auditDeclineList" style="font-size:0.8rem; color:#fca5a5; line-height:1.7;"></div>126 </div>127</div>128 129<script>130// Load audit panel for a given submission ID131async function loadAuditPanel(submissionId) {132 try {133 const resp = await fetch('/audit/' + submissionId);134 const data = await resp.json();135 renderAuditPanel(data);136 } catch(e) {137 document.getElementById('auditSummaryText').textContent = 'Audit data unavailable.';138 }139}140 141function renderAuditPanel(data) {142 const decision = data.decision || data.decision;143 const isApproved = decision === 'APPROVED';144 145 // Badge146 const badge = document.getElementById('auditDecisionBadge');147 badge.textContent = decision;148 badge.style.borderColor = isApproved ? '#00e5a0' : '#ef4444';149 badge.style.color = isApproved ? '#00e5a0' : '#ef4444';150 151 // Summary152 document.getElementById('auditSummaryText').textContent = data.overall_summary || '';153 154 // Score bar155 const score = data.audit_score || 0;156 document.getElementById('auditScoreBar').style.width = score + '%';157 document.getElementById('auditScoreBar').style.background = score > 70 ? '#00e5a0' : score > 40 ? '#f59e0b' : '#ef4444';158 document.getElementById('auditScoreVal').textContent = score + '%';159 160 // Factors161 const factors = data.decision_factors || [];162 const container = document.getElementById('auditFactors');163 container.innerHTML = '';164 factors.forEach(function(f) {165 const outcomeColor = {166 'PASS': '#00e5a0', 'APPROVED': '#00e5a0', 'ISSUED': '#00e5a0', 'CALCULATED': '#00d4ff',167 'FAIL': '#ef4444', 'DECLINED': '#ef4444', 'DECLINE': '#ef4444',168 'REFER': '#f59e0b', 'NOT ISSUED': '#f59e0b'169 }[f.outcome] || '#7a9ab8';170 171 const row = document.createElement('div');172 row.style.cssText = 'background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.07);padding:0.6rem 0.9rem;border-radius:2px;';173 row.innerHTML = `174 <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.3rem;">175 <span style="font-size:0.7rem;color:#f0f6ff;font-weight:600;">${f.agent}</span>176 <span style="font-size:0.65rem;font-weight:700;color:${outcomeColor};letter-spacing:0.1em;">${f.outcome}</span>177 </div>178 <div style="font-size:0.65rem;color:#7a9ab8;margin-bottom:0.2rem;text-transform:uppercase;letter-spacing:0.08em;">${f.factor}</div>179 <div style="font-size:0.72rem;color:#a8c0d8;line-height:1.5;">${f.detail}</div>180 `;181 container.appendChild(row);182 });183 184 // Decline reasons185 const reasons = data.decline_reasons || [];186 if (!isApproved && reasons.length > 0) {187 const reasonsDiv = document.getElementById('auditDeclineReasons');188 reasonsDiv.style.display = 'block';189 const list = document.getElementById('auditDeclineList');190 list.innerHTML = reasons.map(function(r, i) {191 return `<div style="margin-bottom:0.4rem;"><span style="color:#ef4444;margin-right:0.4rem;">${i+1}.</span>${r}</div>`;192 }).join('');193 }194}195 196// Auto-load if submission ID is in the page197document.addEventListener('DOMContentLoaded', function() {198 // Replace with however you pass submission_id to your page199 // e.g. from a data attribute: <div id="auditPanel" data-submission-id="123">200 const panel = document.getElementById('auditPanel');201 const sid = panel && panel.dataset.submissionId;202 if (sid) loadAuditPanel(sid);203});204</script>205"""206 