console.log(JSON.stringify({schema:1,harness:'prospectos-frontend-final-acceptance',pass:false,error:'--base-url and --start-server are mutually exclusive'},null,2));
check('dom.critical-ids','critical operator DOM IDs are present',all(expectedIds,id=>htmlIds.has(id)),listMissing(expectedIds,id=>htmlIds.has(id)).join(', '));
check('routes.contracts','all critical API route contracts are referenced by the client',all(routeContracts,route=>js.includes(route)),listMissing(routeContracts,route=>js.includes(route)).join(', '));
check('routes.authenticated','protected API requests include cookie credentials',js.includes("credentials:'include'")&&js.includes('jsonRequest'));
check('routes.no-arbitrary-target-fetch','browser does not fetch arbitrary target URLs directly',!/fetch\s*\(\s*(?:url|target|website|href)\b/i.test(js));
check('crm.stage-contract','CRM stage definitions exactly match the canonical pipeline',JSON.stringify(crmStages)===JSON.stringify(canonicalStages),`actual=${JSON.stringify(crmStages)}`);
check('crm.stage-control','detail stage control exposes only canonical stages',canonicalStages.every(stage=>pipelineControl.includes(`value="${stage}"`))&&!pipelineControl.includes('value="review"')&&!pipelineControl.includes('value="suppressed"'));
check('crm.interaction-form-contract','interaction form uses kind/body and canonical outcomes',interactionControl.includes('name="kind"')&&interactionControl.includes('name="body"')&&canonicalOutcomes.every(outcome=>interactionControl.includes(`value="${outcome}"`))&&!interactionControl.includes('name="type"')&&!interactionControl.includes('name="summary"'));
check('crm.interaction-payload-contract','interaction writes use the backend kind/body payload contract',/JSON\.stringify\(\{\s*kind:\s*data\.kind,\s*body:\s*data\.body/.test(js)&&!/JSON\.stringify\(\{\.\.\.data,outreach:false\}\)/.test(js));
check('manifest.schema','asset manifest has a supported schema and asset lists',Boolean(manifest&&manifest.schema===1&&Array.isArray(manifest.entrypoints)&&Array.isArray(manifest.publicAssets)&&manifest.integrity&&manifestAssets.length),manifest?'':'manifest unavailable');
if(manifestAssets){
check('manifest.assets-exist','every manifest asset exists and is non-empty',all(manifestAssets,asset=>files[asset]?.length>0),listMissing(manifestAssets,asset=>files[asset]?.length>0).join(', '));
check('assets.linked-local','all local HTML assets exist and are non-empty',all(linkedAssets,asset=>files[asset]?.length>0),listMissing(linkedAssets,asset=>files[asset]?.length>0).join(', '));
check('css.responsive','responsive CSS covers mobile layouts and critical grids',/@media\s*\(\s*max-width\s*:\s*700px\s*\)/.test(css)&&all(['.saved-view-controls','.website-scan-grid','.crm-two-col','.reports-grid','.outreach-panel','.pipeline-board','.ai-provider-grid'],selector=>css.includes(selector)));
constsafetyCopy=['No outreach from this workspace.','Suppression always wins.','Sending is disabled by default.','Approval does not send a message.','no outreach will be sent','AUTOMATED_OUTREACH_ENABLED=false'];
check('safety.no-send-copy','persistent no-send and approval safety copy is present',all(safetyCopy,phrase=>combined.includes(phrase)),listMissing(safetyCopy,phrase=>combined.includes(phrase)).join(' | '));
check('safety.no-send-controls','static HTML exposes no send, delivery, or campaign control',!buttonLabels.some(label=>/\b(send|deliver|campaign|scheduledelivery)\b/i.test(label)));
check('safety.approval-gated','approval actions require explicit human confirmation and remain non-delivering',all(approvalTokens,token=>js.includes(token)),listMissing(approvalTokens,token=>js.includes(token)).join(', '));
constsuppressionTokens=['statusOf',"st==='suppressed'","renderAiState('suppressed')","renderOutreachState('suppressed')",'suppression','Do not contact'];
check('safety.suppression-precedence','suppression disables AI/outreach and preserves do-not-contact state',all(suppressionTokens,token=>combined.includes(token)),listMissing(suppressionTokens,token=>combined.includes(token)).join(', '));
check('safety.source-disabled','discovery remains disabled until an approved source is enabled',all(['Discovery is disabled by default.','enabled:false','This source is disabled. Enable it only after review.'],token=>combined.includes(token)));
check('safety.no-external-network','client has no direct provider or target network origins',!/(?:fetch|XMLHttpRequest|WebSocket)\s*\(\s*[`'\"]https?:\/\//i.test(js));
check('ai-provider.write-only','AI provider keys are write-only and cleared after save',all(['type="password"','autocomplete="new-password"',"input.value=''",'input[type="password"]'],token=>combined.includes(token))&&!/localStorage[^\n]*(?:nous|firecrawl|api[_-]?key)/i.test(combined));
check('ai-provider.admin-states','AI provider settings expose safe status states and admin-only messaging',all(['/api/v1/ai/provider-config','/api/v1/admin/ai-provider-config/test','Not configured','Invalid configuration','Administrator access required'],token=>combined.includes(token)));