File size: 25,172 Bytes
a019fdc
19fb27d
 
 
 
 
 
 
 
 
 
 
d35898f
d6cf833
19fb27d
 
 
 
 
d6cf833
19fb27d
d6cf833
 
19fb27d
 
 
258970b
d6cf833
19fb27d
d6cf833
19fb27d
 
d6cf833
 
 
 
 
 
 
 
 
 
 
 
19fb27d
d6cf833
19fb27d
 
 
 
 
 
 
 
 
 
d6cf833
d35898f
 
d6cf833
d35898f
 
 
d6cf833
 
258970b
 
 
 
 
 
 
 
 
d6cf833
 
 
19fb27d
1
2
3
4
5
6
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
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Uraion FinStruct</title>
  <style>
    :root{color-scheme:dark;--bg:#07111f;--card:#0e1c2f;--ink:#e8f0fb;--muted:#8fa5bd;--accent:#64d8c4;--line:#243a53}
    *{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 20% 0,#143457 0,var(--bg) 42%);color:var(--ink);font:16px/1.55 ui-sans-serif,system-ui,sans-serif}
    main{max-width:1000px;margin:auto;padding:64px 24px}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:1;margin:.2em 0;letter-spacing:-.045em}h1 span{color:var(--accent)}
    p{color:var(--muted);max-width:720px}.eyebrow{color:var(--accent);font-weight:700;letter-spacing:.12em;text-transform:uppercase;font-size:.78rem}
    .card{background:color-mix(in srgb,var(--card) 92%,transparent);border:1px solid var(--line);border-radius:18px;padding:24px;margin-top:32px;box-shadow:0 22px 70px #0005}
    label{display:block;font-weight:650;margin:14px 0 6px}input,select{width:100%;padding:12px;border:1px solid var(--line);border-radius:10px;background:#07111f;color:var(--ink)}
    .button-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:18px}button{background:var(--accent);color:#03201b;border:1px solid var(--accent);border-radius:10px;padding:12px 18px;font-weight:800;cursor:pointer}button.secondary{background:transparent;color:var(--accent)}button:disabled{opacity:.45}
    pre{white-space:pre-wrap;word-break:break-word;max-height:620px;overflow:auto;background:#050b14;border:1px solid var(--line);border-radius:12px;padding:18px;font-size:.82rem}
    .note{font-size:.9rem}.links a{color:var(--accent);margin-right:18px}.status{min-height:1.5em;color:var(--accent)}
  </style>
</head>
<body><main>
  <div class="eyebrow">Uraion Labs · FinStruct v0.3.3 · browser profile v0.3.1</div>
  <h1>Auditable local AI for <span>financial documents.</span></h1>
  <p>Try a synthetic Item 4.02 example instantly or upload your own SEC filing. Core financial facts, controls disclosures, and six non-reliance fields are extracted in your browser with evidence, confidence, and explicit abstention. No file leaves this page.</p>
  <div class="links"><a href="https://colab.research.google.com/github/arnavprabhu/uraion-finstruct/blob/main/notebooks/finstruct_item_402_quickstart.ipynb">Run Python in Colab</a><a href="https://github.com/arnavprabhu/uraion-finstruct/releases/tag/v0.3.3">v0.3.3 release</a><a href="https://huggingface.co/datasets/UraionLabs/FilingsBench">FilingsBench</a><a href="https://github.com/arnavprabhu/uraion-finstruct/blob/main/docs/non_reliance_temporal_audit_v0.2.md">Temporal audit</a><a href="https://huggingface.co/datasets/UraionLabs/FilingsBench/blob/main/non_reliance/review_template_starter.csv">Four-filing review</a></div>
  <section class="card">
    <label for="file">SEC primary filing HTML</label><input id="file" type="file" accept=".html,.htm,text/html">
    <label for="url">Original SEC URL (needed for accession evidence)</label><input id="url" type="url" placeholder="https://www.sec.gov/Archives/edgar/data/…/filing.htm">
    <label for="mode">Extraction profile</label><select id="mode"><option value="all">All supported profiles</option><option value="facts">Financial facts only</option><option value="controls">Controls disclosures only</option><option value="non_reliance">8-K Item 4.02 only</option></select>
    <div class="button-row"><button id="sample" class="secondary" type="button">Try synthetic Item 4.02 example</button><button id="run" type="button" disabled>Extract locally</button></div><p class="status" id="status"></p>
    <pre id="output">Choose a filing saved from sec.gov to begin.</pre>
    <p class="note">The built-in example is a synthetic test fixture, not a benchmark record, external submission, or adoption signal. This compact browser profile predates the v0.3.2 temporal-audit fixes. It cannot enrich a missing filing date from the SEC Submissions API and may abstain where the measured Python path succeeds. The temporal set has accuracy null; narrative candidate labels remain pending independent review.</p>
  </section>
</main><script>
const file=document.querySelector('#file'),run=document.querySelector('#run'),sample=document.querySelector('#sample'),mode=document.querySelector('#mode'),out=document.querySelector('#output'),status=document.querySelector('#status');
const SAMPLE_HTML=`<!doctype html><html><body>
<ix:nonNumeric name="dei:DocumentType">8-K</ix:nonNumeric>
<h2>Item 4.02(a) Non-Reliance on Previously Issued Financial Statements or a Related Audit Report or Completed Interim Review.</h2>
<p>On April 15, 2024, the Audit Committee concluded that the Company's previously issued financial statements for the year ended December 31, 2023 should no longer be relied upon because of errors involving revenue recognition and classification within the statement of cash flows.</p>
<p>The financial statements will be restated in an amended Annual Report on Form 10-K/A.</p>
<p>The Audit Committee discussed these matters with the Company's independent registered public accounting firm, Example LLP.</p>
<p>Item 5.02 Departure of Directors.</p>
</body></html>`;
let activeSampleHtml=null;
const sourceName=()=>activeSampleHtml?'synthetic-item-4-02.html':file.files[0]?.name||'local-filing.html';
file.addEventListener('change',()=>{activeSampleHtml=null;run.disabled=!file.files.length;status.textContent=file.files.length?'Ready to extract your local filing.':''});
const text=t=>(t.textContent||'').replace(/\u00a0/g,' ').trim().replace(/\s+/g,' ');
const ev=(t,url)=>({source_url:url||sourceName(),method:'inline_xbrl_fact',concept:t.getAttribute('name'),context_ref:t.getAttribute('contextref'),raw_text:text(t)});
const absent=reason=>({value:null,status:'abstained',confidence:0,evidence:[],reason});
function dateValue(s){const d=new Date(s.replace(' ,',','));return Number.isNaN(d.valueOf())?null:d.toISOString().slice(0,10)}
function present(value,evidence,confidence=1){return {value,status:'present',confidence,evidence:[evidence],reason:null}}
function extract(html,url){const started=performance.now(),doc=new DOMParser().parseFromString(html,'text/html'),tags=[...doc.querySelectorAll('[name]')];
 const find=names=>tags.find(t=>names.some(n=>n.toLowerCase()===(t.getAttribute('name')||'').toLowerCase())&&text(t));
 const dei=(names,kind)=>{const t=find(names);if(!t)return absent(`No inline-XBRL fact found for ${names.join(', ')}`);let v=text(t);if(kind==='cik')v=v.replace(/\D/g,'').padStart(10,'0');if(kind==='form')v=v.replace(/\s/g,'').toUpperCase();if(kind==='date'){v=dateValue(v);if(!v)return absent('Unsupported inline-XBRL date format')}return present(v,ev(t,url))};
 const fields={registrant_name:dei(['dei:EntityRegistrantName']),cik:dei(['dei:EntityCentralIndexKey'],'cik'),form:dei(['dei:DocumentType'],'form'),filing_date:dei(['dei:DocumentFilingDate'],'date'),period_end:dei(['dei:DocumentPeriodEndDate'],'date')};
 const m=url.match(/\/(\d{10})(\d{2})(\d{6})\//);fields.accession_number=m?present(`${m[1]}-${m[2]}-${m[3]}`,{source_url:url,method:'sec_archive_url',concept:null,context_ref:null,raw_text:m[0]}):absent('Accession number is absent from the SEC archive URL');
 const contexts={};for(const c of [...doc.querySelectorAll('*')].filter(e=>e.tagName.toLowerCase().endsWith('context'))){const nodes=[...c.querySelectorAll('*')],get=s=>nodes.find(n=>n.tagName.toLowerCase().endsWith(s));contexts[c.id]={start:dateValue(text(get('startdate')||document.createElement('i'))),end:dateValue(text(get('enddate')||get('instant')||document.createElement('i'))),dim:nodes.some(n=>/explicitmember|typedmember/.test(n.tagName.toLowerCase()))}}
 const numeric=(names)=>{let candidates=[];for(const t of tags){const p=names.findIndex(n=>n.toLowerCase()===(t.getAttribute('name')||'').toLowerCase());if(p<0)continue;const c=contexts[t.getAttribute('contextref')||''];if(!c||c.dim||c.end!==fields.period_end.value||!c.start)continue;const days=(new Date(c.end)-new Date(c.start))/86400000,form=fields.form.value;if(form==='10-K'&&(days<250||days>410)||form==='10-Q'&&(days<60||days>110))continue;let raw=text(t).replace(/[$,]/g,'').replace(/^\((.*)\)$/,'-$1'),v=Number(raw)*10**Number(t.getAttribute('scale')||0);if(Number.isFinite(v))candidates.push({rank:p*1000+Math.abs(days-(form==='10-K'?365:91)),t,v})}if(!candidates.length)return absent('No matching non-dimensional duration fact for the filing period');candidates.sort((a,b)=>a.rank-b.rank);const best=candidates.filter(x=>x.rank===candidates[0].rank);if(new Set(best.map(x=>x.v)).size>1)return absent('Conflicting equally ranked inline-XBRL facts');return present(best[0].v,ev(best[0].t,url),.98)};
 fields.revenue=numeric(['us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax','us-gaap:Revenues','us-gaap:SalesRevenueNet']);fields.net_income=numeric(['us-gaap:NetIncomeLoss','us-gaap:ProfitLoss']);return {document:{source_url:url||sourceName(),schema_version:'filing-v0.1'},fields,telemetry:{latency_ms:+(performance.now()-started).toFixed(3),peak_python_memory_mb:null,inference_cost_usd:0,model:'deterministic-inline-xbrl-browser-v0.1'}}}
function extractControls(html,url){const started=performance.now(),doc=new DOMParser().parseFromString(html,'text/html');doc.querySelectorAll('script,style,noscript,[hidden],[aria-hidden="true"]').forEach(t=>t.remove());doc.querySelectorAll('p,div,h1,h2,h3,h4,h5,h6,li,tr,br').forEach(t=>t.append('\n'));const visible=(doc.body.textContent||'').split('\n').map(x=>x.replace(/\u00a0/g,' ').trim().replace(/\s+/g,' ')).filter(Boolean).join('\n');const formTag=[...doc.querySelectorAll('[name]')].find(t=>(t.getAttribute('name')||'').toLowerCase()==='dei:documenttype'),form=formTag?text(formTag).replace(/\s/g,'').toUpperCase():null;
 const spec=form==='10-K'?{label:'Item 9A. Controls and Procedures',head:/(^|\n)\s*i\s*tem\s+9a\b/ig,next:/(^|\n)\s*i\s*tem\s+9b\b/i}:form==='10-Q'?{label:'Part I, Item 4. Controls and Procedures',head:/(^|\n)\s*i\s*tem\s+4\b/ig,next:/(^|\n)\s*part\s+ii\b/i}:null;let section=null;if(spec){const candidates=[];for(const m of visible.matchAll(spec.head)){const tail=visible.slice(m.index+m[0].length),n=tail.search(spec.next),end=n<0?visible.length:m.index+m[0].length+n,s=visible.slice(m.index,end);if(/internal controls? over financial reporting|material weakness(?:es)?|disclosure controls and procedures/i.test(s))candidates.push({label:spec.label,text:s,start:m.index})}section=candidates.sort((a,b)=>b.text.length-a.text.length)[0]||null}
 const fields={},fail='Could not locate the controls section for a supported 10-K or 10-Q';if(!section){for(const name of ['icfr_effectiveness','disclosure_controls_effectiveness','material_weakness_disclosed','remediation_status'])fields[name]=absent(fail)}else{const sentences=section.text.split(/(?<=\.)\s+|\n+/).map(s=>s.trim()).filter(Boolean),find=rx=>sentences.find(s=>rx.test(s)),evidence=(s,method)=>({source_url:url||sourceName(),method,concept:null,context_ref:null,raw_text:s,section:section.label,start_char:section.start+section.text.indexOf(s),end_char:section.start+section.text.indexOf(s)+s.length});
  let s=find(/(?:management|we).*(?:concluded|determined|assessed).*internal controls? over financial reporting.*(?:not effective|ineffective)|(?:management|we).*did not maintain effective internal controls? over financial reporting/i);if(s)fields.icfr_effectiveness=present('ineffective',evidence(s,'current_management_conclusion'),.99);else if(s=find(/(?:management|we).*(?:concluded|determined|assessed).*internal controls? over financial reporting.*(?:was|were|is|are) effective/i))fields.icfr_effectiveness=present('effective',evidence(s,'current_management_conclusion'),.99);else fields.icfr_effectiveness=absent('No explicit current-period management conclusion on ICFR effectiveness');
  s=find(/(?:concluded|determined).*disclosure controls and procedures.*(?:not effective|ineffective)/i);if(s)fields.disclosure_controls_effectiveness=present('ineffective',evidence(s,'current_management_conclusion'),.99);else if(s=find(/(?:concluded|determined).*disclosure controls and procedures.*(?:was|were|is|are).*(?:effective)/i))fields.disclosure_controls_effectiveness=present('effective',evidence(s,'current_management_conclusion'),.99);else fields.disclosure_controls_effectiveness=absent('No explicit current-period management conclusion on disclosure-controls effectiveness');
  s=find(/(?:due to|because of).*(?:material weakness(?:es)?)|identified (?:a |the following )?material weakness(?:es)?|material weakness(?:es)?.*(?:remain|continue|not .*remediated)/i);if(s)fields.material_weakness_disclosed=present(true,evidence(s,'affirmative_disclosure'),.98);else if(s=find(/no material weakness(?:es)? (?:were|was|have been|has been) (?:identified|found|noted)|did not identify (?:any )?material weakness(?:es)?/i))fields.material_weakness_disclosed=present(false,evidence(s,'explicit_negative_disclosure'),.99);else if(fields.icfr_effectiveness.value==='effective')fields.material_weakness_disclosed=present(false,{...fields.icfr_effectiveness.evidence[0],method:'sec_icfr_consistency_inference'},.97);else fields.material_weakness_disclosed=absent('No affirmative, explicit-negative, or effective-ICFR evidence');
  if(fields.material_weakness_disclosed.status==='abstained')fields.remediation_status=absent('Material-weakness status is unresolved');else if(fields.material_weakness_disclosed.value===false){s=find(/material weakness(?:es)?.*(?:has|have) been (?:fully )?remediated/i);fields.remediation_status=s?present('completed',evidence(s,'explicit_remediation_status'),.98):present('not_applicable',fields.material_weakness_disclosed.evidence[0],.97)}else{s=find(/(?:continue|ongoing|in progress).*remediat|(?:not|has not|have not).*(?:fully )?remediated|remain(?:s|ing)? unremediated/i);fields.remediation_status=s?present('ongoing',evidence(s,'explicit_remediation_status'),.97):present('not_disclosed',fields.material_weakness_disclosed.evidence[0],.7)}}return {document:{source_url:url||sourceName(),schema_version:'controls-v0.1'},fields,telemetry:{latency_ms:+(performance.now()-started).toFixed(3),peak_python_memory_mb:null,inference_cost_usd:0,model:'deterministic-controls-browser-v0.1'}}}
function extractNonReliance(html,url){const started=performance.now(),doc=new DOMParser().parseFromString(html,'text/html');doc.querySelectorAll('script,style,noscript,[hidden],[aria-hidden="true"]').forEach(t=>t.remove());doc.querySelectorAll('p,div,h1,h2,h3,h4,h5,h6,li,tr,br').forEach(t=>t.append('\n'));const visible=(doc.body.textContent||'').split('\n').map(x=>x.replace(/\u00a0/g,' ').trim().replace(/\s+/g,' ')).filter(Boolean).join('\n'),source=url||sourceName();const formTag=[...doc.querySelectorAll('[name]')].find(t=>(t.getAttribute('name')||'').toLowerCase()==='dei:documenttype'),form=formTag?text(formTag).replace(/\s/g,'').toUpperCase():null,names=['item_4_02_variant','non_reliance_scope','latest_conclusion_or_notice_date','restatement_status','auditor_discussion_disclosed','accounting_topics'];
 const stop=/^\s*item\s+(?:4\.03|[5-9]\.\d{2})\b/im,heading=/^\s*item\s+4\.02(?:\s*\(\s*[ab]\s*\))?\b[^\n]{0,180}/gim,signal=/should no longer be relied upon|prevent future reliance|received (?:notice|notification)|\brestat(?:e|ed|ement)|independent accountant/gi,candidates=[];if(form==='8-K'||form==='8-K/A'){for(const h of visible.matchAll(heading)){const tail=visible.slice(h.index+h[0].length),n=tail.search(stop),r=tail.search(/^\s*item\s+4\.02(?:\s*\(\s*[ab]\s*\))?\b/im),ends=[n,r].filter(x=>x>=0),end=h.index+h[0].length+(ends.length?Math.min(...ends):tail.length),candidate=visible.slice(h.index,end);signal.lastIndex=0;const score=[...candidate.matchAll(signal)].length;if(score)candidates.push({text:candidate,start:h.index,score})}}const section=candidates.sort((a,b)=>b.score-a.score||b.text.length-a.text.length)[0];if(!section){const fields={};for(const name of names)fields[name]=absent('Could not locate Item 4.02 in a supported Form 8-K or 8-K/A');return {document:{source_url:source,schema_version:'non-reliance-v0.1'},fields,telemetry:{latency_ms:+(performance.now()-started).toFixed(3),peak_python_memory_mb:null,inference_cost_usd:0,model:'deterministic-item-4.02-browser-v0.1'}}}
 const nl=section.text.indexOf('\n'),body=nl<0?section:{text:section.text.slice(nl+1),start:section.start+nl+1},first=(patterns,target=body.text)=>patterns.map(rx=>rx.exec(target)).filter(Boolean).sort((a,b)=>a.index-b.index)[0]||null,evidence=(target,m,method)=>{const before=target.text.slice(0,m.index),left=Math.max(before.lastIndexOf('. '),before.lastIndexOf('\n'))+1,after=target.text.slice(m.index+m[0].length),stops=[after.indexOf('. '),after.indexOf('\n')].filter(x=>x>=0),right=stops.length?m.index+m[0].length+Math.min(...stops)+1:target.text.length,lead=target.text.slice(left,right).match(/^\s*/)[0].length,start=left+lead,raw=target.text.slice(start,right).trim().replace(/\s+/g,' ');return {source_url:source,method,concept:null,context_ref:null,raw_text:raw,section:'Item 4.02. Non-Reliance on Previously Issued Financial Statements or a Related Audit Report or Completed Interim Review',start_char:target.start+start,end_char:target.start+right}},p=(value,confidence,e,reason=null)=>({value,status:'present',confidence,evidence:Array.isArray(e)?e:[e],reason});
 const explicitA=/item\s+4\.02\s*\(\s*a\s*\)|^\s*\(\s*a\s*\)/im.exec(section.text),explicitB=/item\s+4\.02\s*\(\s*b\s*\)|^\s*\(\s*b\s*\)/im.exec(section.text),implicitA=/(?:audit committee|board of directors|management|the company)[\s\S]{0,260}(?:concluded|determined)[\s\S]{0,900}(?:financial statements?|financials)[\s\S]{0,400}should no longer be relied upon/i.exec(section.text),implicitB=/(?:was advised by|advised (?:the company|us)|as informed by|received (?:a\s+)?(?:notice|notification) from)[\s\S]{0,220}(?:independent|accountant|auditor|accounting firm)/i.exec(section.text),am=explicitA||implicitA,bm=explicitB||implicitB;let variant=am&&bm?p('a_and_b',.99,[evidence(section,am,'item_4_02_variant'),evidence(section,bm,'item_4_02_variant')]):bm?p('b',.99,evidence(section,bm,'item_4_02_variant')):am?p('a',.98,evidence(section,am,'item_4_02_variant')):absent('Item 4.02 section does not identify paragraph (a) or (b) trigger facts');
 const fs=first([/(?:financial statements?|financials)[\s\S]{0,300}should no longer be relied upon/i,/should no longer be relied upon[\s\S]{0,180}(?:financial statements?|financials)/i]),ar=first([/(?:audit (?:reports?|opinions?)|reports? of (?:the )?independent|completed interim reviews?)[\s\S]{0,320}(?:should no longer be relied upon|prevent future reliance|recalled|withdrawn)/i,/(?:prevent future reliance|should no longer be relied upon)[\s\S]{0,320}(?:audit (?:reports?|opinions?)|completed interim reviews?)/i,/(?:accompanying|previously issued) audit report[\s\S]{0,260}should no longer be relied upon/i,/report of .{1,100}(?:included|dated)[\s\S]{0,300}should no longer be relied upon/i]),scope=fs&&ar?p('both',.98,[evidence(body,fs,'explicit_non_reliance_target'),evidence(body,ar,'explicit_non_reliance_target')]):fs?p('financial_statements',.99,evidence(body,fs,'explicit_non_reliance_target')):ar?p('audit_report_or_completed_interim_review',.99,evidence(body,ar,'explicit_non_reliance_target')):absent('No explicit non-reliance target found in Item 4.02');
 const months='January|February|March|April|May|June|July|August|September|October|November|December',dateText=`(?:${months})\\s+\\d{1,2},\\s+\\d{4}`,datePatterns=[new RegExp(`on\\s+(${dateText})[\\s\\S]{0,280}(?:audit committee|board of directors|management|company)[\\s\\S]{0,220}(?:concluded|determined)`,'ig'),new RegExp(`on\\s+(${dateText})[\\s\\S]{0,280}(?:was advised|received (?:a\\s+)?(?:notice|notification))`,'ig'),new RegExp(`(?:concluded|determined)\\s+on\\s+(${dateText})`,'ig')],dated=[];for(const rx of datePatterns)for(const m of body.text.matchAll(rx)){const d=new Date(m[1]);if(!Number.isNaN(d.valueOf()))dated.push({d,m})}dated.sort((a,b)=>b.d-a.d);const latest=dated.length?p(dated[0].d.toISOString().slice(0,10),.98,evidence(body,dated[0].m,'explicit_conclusion_or_notice_date')):absent('No explicit conclusion or accountant-notice date found');
 const completed=first([/(?:error|misclassification)[\s\S]{0,180}has been corrected/i,/(?:has|have)\s+(?:already\s+)?filed[\s\S]{0,160}(?:amended|restated)/i,/restated financial statements[\s\S]{0,180}(?:were|have been)\s+filed/i]),planned=first([/(?:will|should)\s+be\s+restated/i,/restatement[\s\S]{0,100}(?:is|required|will be)/i,/(?:plans?|intends?|expects?)\s+to\s+file[\s\S]{0,180}(?:amended|amendments?)/i,/will\s+(?:file|amend)[\s\S]{0,180}(?:10-[KQ]\/A|amended|financial statements)/i,/10-[KQ]\/A[\s\S]{0,180}will\s+be\s+filed/i]),restatement=completed?p('completed',.97,evidence(body,completed,'explicit_restatement_status')):planned?p('planned',.97,evidence(body,planned,'explicit_restatement_status')):scope.status==='present'?p('not_disclosed',.75,scope.evidence,'A non-reliance target is explicit but no restatement status is stated'):absent('Non-reliance scope is unresolved');
 const discussed=first([/(?:after|following)\s+(?:discussion|consultation)s?\s+with[\s\S]{0,180}(?:independent|auditor|accounting firm|(?:LLP|LLC|P\.?C\.?))/i,/(?:audit committee|management|company|board)[\s\S]{0,180}(?:discussed|consulted)[\s\S]{0,220}(?:independent|auditor|accounting firm|(?:LLP|LLC|P\.?C\.?))/i,/(?:discussed|consulted)[\s\S]{0,180}[A-Z][A-Za-z& .'-]{1,70}(?:LLP|LLC|P\.?C\.?)/, /following discussions[\s\S]{0,120}(?:independent|auditor|accounting firm)/i]),notDiscussed=first([/(?:did|has|have)\s+not\s+(?:discuss|consult)/i]),discussion=discussed&&(!notDiscussed||discussed.index<=notDiscussed.index)?p(true,.98,evidence(body,discussed,'explicit_auditor_discussion')):notDiscussed?p(false,.98,evidence(body,notDiscussed,'explicit_no_auditor_discussion')):absent('No explicit statement about discussion with the independent accountant');
 const topicPatterns=[['revenue_recognition',/revenue recognition|recognition of revenue|incorrect cutoff[\s\S]{0,100}revenue|revenue transaction[\s\S]{0,100}(?:cutoff|incorrect)/i],['cash_flow_classification',/(?:(?:misclassif|reclassif|classification)[\s\S]{0,140}(?:statement of cash flows|cash flows?))|(?:(?:statement of cash flows|cash flows?)[\s\S]{0,140}(?:misclassif|reclassif|classified|presented as))|(?:operating activities[\s\S]{0,140}(?:investing|financing) activities)|(?:investing activities[\s\S]{0,140}(?:operating|financing) activities)|(?:financing activities[\s\S]{0,140}(?:operating|investing) activities)/i],['goodwill_or_impairment',/goodwill|impairment/i],['inventory',/inventory/i],['tax',/sales and use tax|income tax|tax expense|tax provision/i],['loan_or_credit',/consumer loans?|loan portfolio|credit enhancement/i],['deposit_classification',/deposit[\s\S]{0,160}(?:classif|interest[- ]bearing)|classif[\s\S]{0,160}deposit/i],['expense_or_accrual',/accru(?:al|ed)|expense recognition/i],['audit_procedure_or_independence',/audit procedures?|auditor independence|independence[\s\S]{0,80}impair|re-audit/i],['digital_assets',/digital assets?|cryptocurrency|bitcoin/i]],topicHits=topicPatterns.map(([name,rx])=>[name,rx.exec(body.text)]).filter(([,m])=>m),error=/\b(?:error|errors|misclassification|misstatement)\b/i.exec(body.text),topics=topicHits.length?p(topicHits.map(([name])=>name),.9,topicHits.map(([,m])=>evidence(body,m,'controlled_accounting_topic'))):error?p(['other'],.7,evidence(body,error,'unclassified_accounting_error')):absent('No accounting-error topic is explicitly supported');
 const fields={item_4_02_variant:variant,non_reliance_scope:scope,latest_conclusion_or_notice_date:latest,restatement_status:restatement,auditor_discussion_disclosed:discussion,accounting_topics:topics};return {document:{source_url:source,schema_version:'non-reliance-v0.1'},fields,telemetry:{latency_ms:+(performance.now()-started).toFixed(3),peak_python_memory_mb:null,inference_cost_usd:0,model:'deterministic-item-4.02-browser-v0.1'}}}
async function execute(){if(!activeSampleHtml&&!file.files.length)return;run.disabled=true;sample.disabled=true;status.textContent='Parsing locally…';try{const html=activeSampleHtml||await file.files[0].text(),url=document.querySelector('#url').value.trim(),profile=mode.value,result=profile==='facts'?extract(html,url):profile==='controls'?extractControls(html,url):profile==='non_reliance'?extractNonReliance(html,url):{facts:extract(html,url),controls:extractControls(html,url),non_reliance:extractNonReliance(html,url)};out.textContent=JSON.stringify(result,null,2);status.textContent=activeSampleHtml?'Done. Synthetic fixture processed locally.':'Done. No file content was uploaded.'}catch(e){status.textContent='Extraction failed';out.textContent=String(e)}finally{run.disabled=!(activeSampleHtml||file.files.length);sample.disabled=false}}
sample.addEventListener('click',async()=>{activeSampleHtml=SAMPLE_HTML;file.value='';mode.value='non_reliance';await execute()});
run.addEventListener('click',execute);
</script></body></html>