AEROLYNT
M013 · SECURITY
` : '
At least two closed revisions are required for a change diff.
'} `; } function bindRevisionViewer(caseId, timeline) { const closed = (timeline?.entries || []).filter(entry => entry.closure_available); if (closed.length < 2) return; const fromSelect = document.getElementById('revisionFrom'); const toSelect = document.getElementById('revisionTo'); const compareButton = document.getElementById('compareRevisionButton'); fromSelect.value = String(closed[closed.length - 2].revision); toSelect.value = String(closed[closed.length - 1].revision); compareButton.addEventListener('click', () => loadRevisionDiff(caseId)); loadRevisionDiff(caseId); } async function showInvestigationWorkspace() { if (!selected?.case_id) { dom.mainPanel.innerHTML = '
Select an investigation to open its workspace.
'; return; } const caseId = encodeURIComponent(selected.case_id); dom.mainPanel.innerHTML = '
Loading investigation workspace…
'; try { const [evidence, actions, readiness, closurePackage, timeline] = await Promise.all([ optionalApi(`/api/investigations/${caseId}/grounded-evidence?include_retired=true`), optionalApi(`/api/investigations/${caseId}/actions`), optionalApi(`/api/investigations/${caseId}/closure-readiness`), optionalApi(`/api/investigations/${caseId}/closure-package`), optionalApi(`/api/investigations/${caseId}/revision-timeline`), ]); renderWorkspace(evidence || [], actions || [], readiness, closurePackage, timeline); bindRevisionViewer(caseId, timeline); } catch (error) { dom.mainPanel.innerHTML = `
${esc(error.message)}
`; } } function renderWorkspace(evidence, actions, readiness, closurePackage, timeline) { const actionCounts = actionSummary(actions); const activeEvidence = evidence.filter(item => item.status !== 'RETIRED').length; const gates = readiness?.gates || []; const ready = readiness?.ready_for_closure === true; const statusText = selected.status || 'OPEN'; const resolved = statusText === 'RESOLVED'; const digest = closurePackage?.integrity?.sha256; const caseId = encodeURIComponent(selected.case_id); const flow = [ ['Sources', true], ['Grounded facts', activeEvidence > 0], ['Evidence diagnostics', Boolean(selected.analysis_snapshot || selected.analyzed_at)], ['Action execution', actions.length > 0 || ready], ['Closure gates', Boolean(readiness)], ['Signed closure', resolved && Boolean(closurePackage)], ]; dom.mainPanel.innerHTML = `
${esc(selected.case_id)} · ${esc(selected.title)}
End-to-end investigation control surface
Verify report
Investigation status

${esc(statusText)}

${esc(selected.case_id)}
${flow.map(([label, active]) => `
${esc(label)}
`).join('')}
${activeEvidence}Active grounded evidence
${actions.length}Investigation actions
${actionCounts.COMPLETED}Completed actions
${ready ? 'READY' : 'BLOCKED'}Closure readiness
Closure readiness
${readiness ? `
${esc(readiness.decision || (ready ? 'READY' : 'BLOCKED'))} · ${gates.filter(item => item.passed).length}/${gates.length} gates passed
${gates.map(gateMarkup).join('')}` : '
Run an analysis to establish deterministic closure gates.
'}
Action execution
${actions.length ? actions.map(item => { const execution = item.execution || {}; const status = execution.status || item.status || 'OPEN'; return `
${esc(item.action_id || item.id)}${esc(status)}
${esc(item.priority || '')}${item.lifecycle_revision ? ` · lifecycle ${esc(item.lifecycle_revision)}` : ''}
`; }).join('') : '
No current investigation actions.
'}
Closure artifacts
${closurePackage ? `
Closure package available.
SHA-256 ${esc(digest)}
` : '
Closure artifacts become available only after the investigation reaches RESOLVED with all M021 gates satisfied.
'}
${timeline ? revisionViewerMarkup(timeline, caseId) : '
Revision history is not available for this investigation.
'}
`; } window.showInvestigationWorkspace = showInvestigationWorkspace; window.loadRevisionDiff = loadRevisionDiff; queueMicrotask(syncWorkspaceButton); })();