1import{r as J,j as e}from"./vendor-react-DlK0ocEt.js";import{w as Z,d as ee,j as H,B as o,A as se,e as te,f as ae,C as v,a as N,g as _,h as q,i as D,t as K}from"./index-SuOLkaBm.js";import{u as W,b as R,a as M}from"./vendor-query-B51qeulE.js";import{L}from"./Layout-CXlC-8yI.js";import{h as I,r as re}from"./discovery-hS775uW_.js";import{j as ie}from"./engagements-D5gHqvyO.js";import{L as f,o as ne,d as X,f as Q,A as le,am as O,aw as oe,ab as S,c as z,aa as Y,T as V}from"./vendor-icons-CnHKZiUe.js";import"./vendor-radix-CU2QiDnB.js";import"./vendor-charts-pmX7lNt8.js";const ce=new Set(["in_progress","ready","review_required","action_required","retryable","publication_blocker"]);function C(t){return typeof t=="string"&&t.trim()?t.trim():null}function de(t){const s=C(t)?.toLowerCase().replace(/[\s-]+/g,"_");if(!s)return null;const r={pending:"in_progress",generating:"in_progress",synthesising:"in_progress",synthesizing:"in_progress",complete:"ready",completed:"ready",assembled:"ready",review:"review_required",fallback:"review_required",template_fallback:"review_required",failed:"retryable",error:"retryable"};return ce.has(s)?s:r[s]??null}function me(t){return Array.isArray(t)?t.reduce((s,r)=>r&&typeof r=="object"&&"synthesisStatus"in r&&r.synthesisStatus==="fallback_template"?s+1:s,0):0}function pe(t){if(Array.isArray(t))return t.map(r=>C(r)).filter(r=>r!==null);const s=C(t);return s?[s]:[]}function U(t){const s=me(t.sections),m=(typeof t.fallbackCount=="number"&&Number.isFinite(t.fallbackCount)&&t.fallbackCount>=0?Math.floor(t.fallbackCount):null)??s,p=C(t.status)?.toLowerCase(),u=de(t.feedbackState)??(p==="failed"?"retryable":p==="assembled"&&m>0?"review_required":p==="assembled"?"ready":"in_progress"),x=(typeof t.retryable=="boolean"?t.retryable:null)??(u==="action_required"||u==="retryable"||u==="publication_blocker");return{state:u,message:C(t.feedbackMessage),details:pe(t.feedbackDetails),retryable:x,fallbackCount:m,catalogVersion:C(t.catalogVersion)}}function Se(){const[,t]=Z("/scoping/:sessionId/complete"),s=t?.sessionId?parseInt(t.sessionId,10):NaN,r=Number.isFinite(s),m=W(),[,p]=ee(),{toast:i}=H(),u=new URLSearchParams(window.location.search),c=u.get("engagementId"),x=u.get("
1clientId"),F=c&&x?`?engagementId=${c}&clientId=${x}`:"",n=R({mutationFn:()=>re(s),onSuccess:a=>{i({title:`Reopened â now at Pass ${a.currentPass}`});const l=m.getQueryData(["/api/discovery/sessions",s]);l?m.setQueryData(["/api/discovery/sessions",s],{...l,currentPass:a.currentPass,nextQuestion:a.nextQuestion,session:{...l.session,currentPass:a.currentPass,status:"in_progress",completedAt:null}}):m.removeQueries({queryKey:["/api/discovery/sessions",s]}),m.invalidateQueries({queryKey:["/api/discovery/sessions"]}),p(`/scoping/${s}${F}`)},onError:a=>{i({title:"Could not reopen",description:a.message,variant:"destructive"})}}),b=R({mutationFn:()=>ie(Number(x),Number(c)),onSuccess:()=>{i({title:"Project analysis started",description:"Creating prefilled assessment and running AI scoringâ¦"}),p(`/clients/${x}/assessment-projects/${c}`)},onError:a=>{i({title:"Could not start analysis",description:a?.message,variant:"destructive"})}}),{data:j}=M({queryKey:["/api/discovery/sessions",s],enabled:r}),[A,P]=J.useState(null),$=R({mutationFn:async()=>{const a=j?.session.clientId;if(!a)throw new Error("Session not loaded");return await(await K("POST",`/api/clients/${a}/discovery/sessions/${s}/generate-policies`)).json()},onSuccess:a=>{P(a.generatedDocumentIds),i({title:a.reused?"Showing existing ISMS policies":"ISMS policy generation started"})},onError:a=>i({title:"Could not start generation",description:a.message,variant:"destructive"})}),k=j?.session.currentPass??0,w=k>=3,d=j?.session.clientId,{data:h}=M({queryKey:["/api/clients",d,"discovery","sessions",s,"generated-documents"],enabled:r&&!!d&&w,refetchInterval:a=>{const l=a.state.data;return!l||l.length===0||l.every(G=>G.status==="assembled"||G.status==="failed")?!1:3e3}}),{data:g}=M({queryKey:["/api/discovery/sessions",s,"proposal-status"],enabled:r,refetchInterval:a=>{const l=a.state.data?.status;return l==="generating"||l==="not_started"?5e3:!1}}),T=R({mutationFn:async()=>{await K("POST",`/api/discovery/sessions/${s}/proposal-retry`)},onSuccess:()=>{i({title:"Retrying proposal generation..."}
1),m.invalidateQueries({queryKey:["/api/discovery/sessions",s,"proposal-status"]})},onError:a=>i({title:"Could not retry proposal",description:a.message,variant:"destructive"})});if(!r)return e.jsx(L,{children:e.jsx("div",{className:"container py-8",children:"Invalid session ID."})});if(!j)return e.jsx(L,{children:e.jsx("div",{className:"flex items-center justify-center min-h-[60vh]",children:e.jsx(f,{className:"w-6 h-6 animate-spin text-muted-foreground"})})});const y=k,B=y===1?"pass1":y===2?"pass2":"final",E=y<3;return e.jsx(L,{children:e.jsxs("div",{className:"container max-w-5xl py-8 space-y-6",children:[c&&e.jsxs(o,{variant:"ghost",size:"sm",className:"-ml-2",onClick:()=>p(`/clients/${x}/assessment-projects/${c}`),"data-testid":"button-completion-back",children:[e.jsx(ne,{className:"w-4 h-4 mr-1"})," Back to project"]}),e.jsxs(se,{children:[e.jsx(X,{className:"w-4 h-4 text-green-600 dark:text-green-400"}),e.jsx(te,{children:E?`Scoping closed at Pass ${y}`:"Scoping complete"}),e.jsx(ae,{children:E?e.jsxs(e.Fragment,{children:["Session #",s," was finished early at Pass ",y,". The Pass ",y," deliverables are ready below. You can also continue into Pass ",y+1," to refine the gap analysis and sizing."]}):e.jsxs(e.Fragment,{children:["Session #",s," finished. Download the deliverables below â the proposal narrative may take a moment to generate."]})})]}),c&&!E&&e.jsx(v,{className:"border-primary/30 bg-primary/5","data-testid":"card-return-to-project",children:e.jsxs(N,{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4 py-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-medium",children:"Ready to run project analysis"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Scoping is complete. Start AI scoring, generate interview questions, and prepare deliverables."})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2 shrink-0",children:[e.jsxs(o,{onClick:()=>b.mutate(),disabled:b.isPending,"data-testid":"button-completion-run-analysis",children:[b.isPending?e.jsx(f,{className:"w-4 h-4 mr-2 animate-spin"}):e.jsx(Q,{className:"w-4 h-4 mr-2"}),"Run analysis"]}),e.jsxs(o,{variant:"outline",onClick:()=>p(`/clients/${x}/assessment-projects/${c}`),"data-testid":"button-completion-return-to-project",children:["Return to project ",e.jsx(le,{className:"w-4 h-4 ml-1"})]})]})]})}),E&&e.jsx(v,{className:"border-primary/30 bg-primary/5",children:e.jsxs(N,{className:"flex items-center justify-between gap-4 py-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-medium",children:"Want to keep going?"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Reopen this session and continue with Pass ",y+1," questions. Outputs above stay available."]})]}),e.jsxs(o,{onClick:()=>n.mutate(),disabled:n.isPending,"data-testid":"button-completion-continue",children:[n.isPending?e.jsx(f,{className:"w-4 h-4 mr-2 animate-spin"}):e.jsx(O,{className:"w-4 h-4 mr-2"}),"Continue to Pass ",y+1]})]})}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsxs(v,{"data-testid":"card-bom-preview-final",children:[e.jsxs(_,{children:[e.jsxs(q,{className:"flex items-center gap-2 text-base",children:[e.jsx(oe,{className:"w-5 h-5"})," Bill of materials"]}),e.jsx(D,{children:"Excel â sized to the answered scope"})]}),e.jsx(N,{children:e.jsx("a",{href:I(s,"bom",B),download:!0,"data-testid":"link-completion-bom",children:e.jsxs(o,{variant:"outline",className:"w-full",children:[e.jsx(S,{className:"w-4 h-4 mr-2"})," Download BOM"]})})})]}),e.jsxs(v,{"data-testid":"card-policy-preview-final",children:[e.jsxs(_,{children:[e.jsxs(q,{className:"flex items-center gap-2 text-base",children:[e.jsx(z,{className:"w-5 h-5"})," Policy"]}),e.jsxs(D,{children:["Markdown â ",k===3?"final policy":"pass-level policy"]})]}),e.jsx(N,{children:e.jsx("a",{href:I(s,"policy",B),download:!0,"data-testid":"link-completion-policy",children:e.jsxs(o,{variant:"outline",className:"w-full",children:[e.jsx(S,{className:"w-4 h-4 mr-2"})," Download policy"]})})})]}),e.jsxs(v,{"data-testid":"card-proposal",children:[e.jsxs(_,{children:[e.jsxs(q,{className:"flex items-center gap-2 text-base",children:[e.jsx(Q,{className:"w-5 h-5"})," Proposal narrative"]}),e.jsx(D,{children:"Stakeholder-ready summary of findings and recommendations"})]}),e.jsx(N,{children:!g||g.status==="generating"||g.status==="not_started"?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground py-2","data-testid":"text-proposal-generating",children:[e.jsx(f,{className:"w-4 h-4 animate-spin"}),"Generating proposal narrative..."]}):g.status==="failed"?e.jsxs("div",{className:"space-y-2","data-testid":"text-proposal-failed",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-destructive",children:[e.jsx(Y,{className:"w-4 h-4"}),"Proposal generation failed."]}),g.error&&e.jsx("p",{className:"text-xs text-muted-foreground",children:g.error}),e.jsxs(o,{size:"sm",variant:"outline",disabled:T.isPending,onClick:()=>T.mutate(),"data-testid":"button-proposal-retry",children:[T.isPending?e.jsx(f,{className:"w-3.5 h-3.5 mr-1.5 animate-spin"}):e.jsx(O,{className:"w-3.5 h-3.5 mr-1.5"}),"Retry"]})]}):e.jsxs("div",{className:"space-y-3",children:[g.narrative&&e.jsxs("div",{className:"text-sm max-h-48 overflow-y-auto p-3 bg-muted/40 rounded border border-border whitespace-pre-wrap","data-testid":"text-proposal-preview",children:[g.narrative.slice(0,800),g.narrative.length>800?"...":""]}),e.jsx("a",{href:I(s,"proposal"),download:!0,"data-testid":"link-completion-proposal",children:e.jsxs(o,{className:"w-full",children:[e.jsx(S,{className:"w-4 h-4 mr-2"})," Download full proposal"]})})]})})]})]}),k===3&&e.jsxs(v,{"data-testid":"card-answers-export",children:[e.jsxs(_,{children:[e.jsxs(q,{className:"flex items-center gap-2 text-base",children:[e.jsx(z,{className:"w-5 h-5"})," Guided interview answers"]}),e.jsx(D,{children:"Excel export of all completed guided interview answers from Pass 1â3."})]}),e.jsx(N,{children:e.jsx("a",{href:I(s,"answers"),download:!0,"data-testid":"link-completion-answers",children:e.jsxs(o,{variant:"outline",className:"w-full",children:[e.jsx(S,{className:"w-4 h-4 mr-2"})," Download full guided interview export"]})})})]}),w&&e.jsxs(v,{"data-testid":"card-isms-policies",children:[e.jsxs(_,{children:[e.jsxs(q,{className:"flex items-center gap-2 text-base",children:[e.jsx(z,{className:"w-5 h-5"})," ISMS policy framework"]}),e.jsx(D,{children:"Synthesise the master ISMS Policy, nine subordinate policies, and a deterministic Exception Register from this session's scoping facts."})]}),e.jsx(N,{className:"space-y-4",children:(()=>{const a=A??(h&&h.length>0?h.map(l=>l.id):null);
1return a?e.jsx("div",{className:"space-y-3",children:a.map(l=>e.jsx(xe,{clientId:j.session.clientId,docId:l},l))}):e.jsxs(o,{onClick:()=>$.mutate(),disabled:$.isPending,"data-testid":"button-generate-policies",children:[$.isPending?e.jsx(f,{className:"w-4 h-4 mr-2 animate-spin"}):e.jsx(Q,{className:"w-4 h-4 mr-2"}),"Generate ISMS Policies"]})})()})]})]})})}const ue=new Set(["synthesised","validated","fallback_template"]);function xe({clientId:t,docId:s}){const r=W(),{toast:m}=H(),p=["/api/clients",t,"discovery","generated-documents",s],{data:i}=M({queryKey:p,refetchInterval:d=>{const h=d.state.data;return h?U(h).state==="in_progress"?3e3:!1:3e3}}),u=R({mutationFn:async()=>{await K("POST",`/api/clients/${t}/discovery/generated-documents/${s}/retry`)},onSuccess:()=>{m({title:"Retrying document generation..."}),r.invalidateQueries({queryKey:p})},onError:d=>m({title:"Could not retry document",description:d.message,variant:"destructive"})});if(!i)return e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground","data-testid":`text-policy-loading-${s}`,children:[e.jsx(f,{className:"w-4 h-4 animate-spin"})," Loading documentâ¦"]});const c=Array.isArray(i.sections)?i.sections:[],x=c.length,F=c.filter(d=>ue.has(d.synthesisStatus)).length,n=U(i),b=n.fallbackCount,j=i.documentType==="master",A=n.state==="review_required",P=n.state==="action_required"||n.state==="retryable"||n.state==="publication_blocker",$=n.state==="in_progress",k=i.status==="assembled"&&!P,w=n.catalogVersion;return e.jsxs("div",{className:"rounded border border-border p-3 space-y-2","data-testid":`row-policy-doc-${s}`,children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[P?e.jsx(Y,{className:"w-4 h-4 text-destructive shrink-0"}):A?e.jsx(V,{className:"w-4 h-4 text-amber-600 dark:text-amber-400 shrink-0"}):i.status==="assembled"?e.jsx(X,{className:"w-4 h-4 text-green-600 dark:text-green-400 shrink-0"}):e.jsx(f,{className:"w-4 h-4 animate-spin shrink-0"}),e.jsx("span",{className:"text-sm font-medium truncate","data-testid":`text-policy-title-${s}`,children:i.title})]}),x>0&&e.jsxs("span",{className:"text-xs text-muted-foreground shrink-0","data-testid":`text-policy-progress-${s}`,children:[F,"/",x," sections"]})]}),w&&j&&e.jsxs("p",{className:"text-xs text-muted-foreground","data-testid":`text-policy-catalog-${s}`,children:["ISO catalog: ",w]}),$&&e.jsx("p",{className:"text-xs text-muted-foreground","data-testid":`text-policy-in-progress-${s}`,children:"Preparing documentâ¦"}),b>0&&e.jsxs("div",{className:"flex items-center gap-1.5 text-xs text-amber-600 dark:text-amber-400","data-testid":`text-policy-fallback-${s}`,children:[e.jsx(V,{className:"w-3.5 h-3.5"}),b," section",b===1?"":"s"," used a template fallback"]}),A&&e.jsxs("div",{className:"rounded border border-amber-300/70 bg-amber-50/60 dark:border-amber-700/60 dark:bg-amber-950/20 p-2.5 space-y-1","data-testid":`text-policy-review-${s}`,children:[e.jsx("p",{className:"text-sm font-medium text-amber-800 dark:text-amber-300",children:"Review required before sharing"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:n.message||"Review the template fallback sections and confirm the document reflects the client's evidence."}),n.details.length>0&&e.jsx("ul",{className:"text-xs text-muted-foreground list-disc pl-4 space-y-0.5",children:n.details.map((d,h)=>e.jsx("li",{children:d},`${s}-review-detail-${h}`))})]}),k&&e.jsxs("div",{className:"flex flex-wrap gap-2 pt-1",children:[e.jsx("a",{href:`/api/clients/${t}/discovery/generated-documents/${s}/markdown`,download:!0,"data-testid":`link-policy-markdown-${s}`,children:e.jsxs(o,{size:"sm",variant:"outline",children:[e.jsx(S,{className:"w-3.5 h-3.5 mr-1.5"})," Markdown"]})}),j&&e.jsx("a",{href:`/api/clients/${t}/discovery/generated-documents/${s}/soa/excel`,download:"statement-of-applicability.xlsx","data-testid":`link-policy-soa-${s}`,children:e.jsxs(o,{size:"sm",variant:"outline",children:[e.jsx(S,{className:"w-3.5 h-3.5 mr-1.5"}),w?`Download ${w} Statement of Applicability`:"Statement of Applicability"]})})]}),P&&e.jsxs("div",{className:"rounded border border-destructive/30 bg-destructive/5 p-2.5 space-y-2","data-testid":`text-policy-action-required-${s}`,children:[e.jsx("p",{className:"text-xs text-destructive","data-testid":`text-policy-failed-${s}`,children:n.message||"Generation failed for this document."}),n.details.length>0&&e.jsx("ul",{className:"text-xs text-muted-foreground list-disc pl-4 space-y-0.5",children:n.details.map((d,h)=>e.jsx("li",{children:d},`${s}-failure-detail-${h}`))}),n.retryable&&e.jsxs(o,{size:"sm",variant:"outline",disabled:u.isPending,onClick:()=>u.mutate(),"data-testid":`button-policy-retry-${s}`,children:[u.isPending?e.jsx(f,{className:"w-3.5 h-3.5 mr-1.5 animate-spin"}):e.jsx(O,{className:"w-3.5 h-3.5 mr-1.5"}),"Retry"]})]})]})}export{Se as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.