Files
ai-exchange/src/web/app.js
T
2026-05-21 20:51:20 +08:00

6872 lines
355 KiB
JavaScript

const healthStatus = document.getElementById('healthStatus');
const refreshBtn = document.getElementById('refreshBtn');
const instrumentIdInput = document.getElementById('instrumentId');
const timeframeInput = document.getElementById('timeframe');
const limitInput = document.getElementById('limit');
const autoRefreshSecondsInput = document.getElementById('autoRefreshSeconds');
const executionStatusFilterInput = document.getElementById('executionStatusFilter');
const sessionFilterInput = document.getElementById('sessionFilter');
const searchTextInput = document.getElementById('searchText');
const trustClassFilterInput = document.getElementById('trustClassFilter');
const lastUpdated = document.getElementById('lastUpdated');
const activeFilters = document.getElementById('activeFilters');
const workbenchNav = document.getElementById('workbenchNav');
const workbenchContent = document.getElementById('workbenchContent');
const workbenchViewLabel = document.getElementById('workbenchViewLabel');
const workbenchSections = Array.from(document.querySelectorAll('[data-workbench-section]'));
const workbenchNavButtons = Array.from(document.querySelectorAll('[data-workbench-target]'));
const systemOpsLinks = Array.from(document.querySelectorAll('[data-system-ops-target]'));
const DEFAULT_WORKBENCH_SECTION = 'trader-mode';
const WORKBENCH_SECTION_ALIASES = {
'pre-market-plan': 'trading-plan',
'post-trade-review': 'journal',
};
const SYSTEM_OPS_SECTION_IDS = new Set([
'overview',
'decision-assistant',
'trading-status',
'runtime-supervisor',
'decision-packet',
'readiness',
'session-focus',
'intraday-candidates',
'execution-tickets',
'alerts',
'visual-reviews',
'position-management',
'operator-console',
'candles',
]);
const overviewCards = document.getElementById('overviewCards');
const decisionAssistantPanel = document.getElementById('decisionAssistantPanel');
const marketStatePanel = document.getElementById('marketStatePanel');
const runtimeStatusPanel = document.getElementById('runtimeStatusPanel');
const decisionPacketPanel = document.getElementById('decisionPacketPanel');
const trustScorePanel = document.getElementById('trustScorePanel');
const liveReadinessPanel = document.getElementById('liveReadinessPanel');
const launchReadinessPanel = document.getElementById('launchReadinessPanel');
const sessionFocusPanel = document.getElementById('sessionFocusPanel');
const preMarketPlanPanel = document.getElementById('preMarketPlanPanel');
const tradeCandidatesPanel = document.getElementById('tradeCandidatesPanel');
const executionTicketsPanel = document.getElementById('executionTicketsPanel');
const alertHistoryPanel = document.getElementById('alertHistoryPanel');
const alertQualityPanel = document.getElementById('alertQualityPanel');
const strategyBacktestPanel = document.getElementById('strategyBacktestPanel');
const backtestInstrumentIdInput = document.getElementById('backtestInstrumentId');
const backtestLimitInput = document.getElementById('backtestLimit');
const backtestRefreshBtn = document.getElementById('backtestRefreshBtn');
const visualReviewsPanel = document.getElementById('visualReviewsPanel');
const positionManagementPanel = document.getElementById('positionManagementPanel');
const operatorConsolePanel = document.getElementById('operatorConsolePanel');
const postTradeReviewPanel = document.getElementById('postTradeReviewPanel');
const canvas = document.getElementById('candlesChart');
const ctx = canvas.getContext('2d');
let autoRefreshTimer = null;
let assistantHistoryKindFilter = loadAssistantHistoryKindFilter();
let assistantDigestPreferenceMode = loadAssistantDigestPreferenceMode();
let assistantDigestProfileKey = loadAssistantDigestProfileKey();
let assistantScanHandoffMarker = loadAssistantScanHandoffMarker();
let assistantFocusCandidateId = loadAssistantFocusCandidateId();
let assistantPreferenceDraft = null;
let assistantPreferenceDraftDirty = false;
let assistantPreferenceDraftVersion = '';
let assistantOperatorNoteDraft = {
body: '',
context: null,
};
let assistantDigestArchiveState = {
profile_key: '',
profile_scope: 'selected_profile',
query_preset: '',
preferred_history_kind: '',
digest_mode: '',
query_text: '',
created_after: '',
created_before: '',
limit: 12,
next_offset: 0,
selected_left_id: null,
selected_right_id: null,
pinned_baseline_id: null,
};
let assistantWorkflowArchiveState = {
profile_key: '',
profile_scope: 'selected_profile',
query_preset: '',
current_session: '',
next_phase: '',
next_artifact_kind: '',
query_text: '',
created_after: '',
created_before: '',
limit: 12,
next_offset: 0,
selected_left_id: null,
selected_right_id: null,
pinned_baseline_id: null,
};
let assistantWorkflowArchiveBridgeContext = null;
let assistantDigestArchiveLastExport = null;
let assistantWorkflowArchiveLastExport = null;
let assistantSurfaceResolutionFilter = 'all';
async function fetchJson(url, options = {}) {
const fetchOptions = { ...options };
const timeoutMs = Number(fetchOptions.timeoutMs || 6000);
delete fetchOptions.timeoutMs;
const controller = new AbortController();
const timeout = window.setTimeout(() => controller.abort(), timeoutMs);
if (!fetchOptions.signal) {
fetchOptions.signal = controller.signal;
}
if (fetchOptions.body) {
fetchOptions.headers = {
'Content-Type': 'application/json',
...(fetchOptions.headers || {}),
};
}
try {
const response = await fetch(url, fetchOptions);
if (!response.ok) {
throw new Error(`${response.status} ${url}`);
}
if (response.status === 204) {
return null;
}
return response.json();
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`request_timeout ${url}`);
}
throw error;
} finally {
window.clearTimeout(timeout);
}
}
async function postJson(url, body = {}) {
return fetchJson(url, {
method: 'POST',
body: JSON.stringify(body),
});
}
function downloadJsonFile(filename, payload) {
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json;charset=utf-8' });
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = filename || 'archive-export.json';
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
window.URL.revokeObjectURL(url);
}
function setText(element, value) {
if (!element) return;
if (window.I18N?.setText) {
window.I18N.setText(element, value);
return;
}
element.textContent = value == null ? '' : String(value);
}
function clearNode(node) {
if (!node) return;
while (node.firstChild) {
node.removeChild(node.firstChild);
}
}
function getStoredWorkbenchSection() {
try {
const sectionId = normalizeWorkbenchSectionId(window.localStorage?.getItem('aiIctActiveWorkbenchSection') || '');
return SYSTEM_OPS_SECTION_IDS.has(sectionId) ? '' : sectionId;
} catch {
return '';
}
}
function storeWorkbenchSection(sectionId) {
try {
window.localStorage?.setItem('aiIctActiveWorkbenchSection', normalizeWorkbenchSectionId(sectionId));
} catch {
// Local storage can be disabled in hardened browser sessions.
}
}
function normalizeWorkbenchSectionId(sectionId) {
const normalized = String(sectionId || '').trim();
return WORKBENCH_SECTION_ALIASES[normalized] || normalized;
}
function getWorkbenchSection(sectionId) {
const normalized = normalizeWorkbenchSectionId(sectionId);
return workbenchSections.find((section) => section.dataset.workbenchSection === normalized) || null;
}
function getPathWorkbenchSection() {
const normalizedPath = window.location.pathname.replace(/\/+$/, '') || '/';
if (normalizedPath === '/trader-mode' || normalizedPath === '/trader-mode.html') {
return 'trader-mode';
}
return '';
}
function activateWorkbenchSection(sectionId, options = {}) {
if (!workbenchSections.length) return;
const fallback = getWorkbenchSection(DEFAULT_WORKBENCH_SECTION) || workbenchSections[0];
const target = getWorkbenchSection(sectionId) || fallback;
const activeId = target.dataset.workbenchSection;
const activeNavId = SYSTEM_OPS_SECTION_IDS.has(activeId) ? 'system-ops' : activeId;
workbenchSections.forEach((section) => {
const isActive = section === target;
section.classList.toggle('is-active', isActive);
section.toggleAttribute('hidden', !isActive);
});
document.body.dataset.activeWorkbenchSection = activeId;
workbenchNavButtons.forEach((button) => {
const isActive = button.dataset.workbenchTarget === activeNavId;
button.classList.toggle('is-active', isActive);
button.setAttribute('aria-current', isActive ? 'page' : 'false');
});
setText(workbenchViewLabel, target.dataset.workbenchLabel || activeId);
if (options.persist !== false) {
storeWorkbenchSection(activeId);
}
if (options.updateHash) {
window.history.replaceState(null, '', `#${activeId}`);
}
if (options.scrollToTop && workbenchContent) {
workbenchContent.scrollTo({ top: 0, behavior: options.smooth ? 'smooth' : 'auto' });
}
window.dispatchEvent(new CustomEvent('workbench-section-change', { detail: { sectionId: activeId } }));
}
function initializeWorkbenchNavigation() {
if (!workbenchNav || !workbenchSections.length) return;
workbenchNav.addEventListener('click', (event) => {
const button = event.target.closest?.('[data-workbench-target]');
if (!button) return;
activateWorkbenchSection(button.dataset.workbenchTarget, {
scrollToTop: true,
smooth: true,
updateHash: true,
});
});
systemOpsLinks.forEach((button) => {
button.addEventListener('click', () => {
activateWorkbenchSection(button.dataset.systemOpsTarget, {
scrollToTop: true,
smooth: true,
updateHash: true,
});
});
});
const hashSection = window.location.hash ? window.location.hash.replace(/^#\/?/, '') : '';
activateWorkbenchSection(hashSection || getPathWorkbenchSection() || getStoredWorkbenchSection() || DEFAULT_WORKBENCH_SECTION, {
persist: false,
scrollToTop: false,
});
}
function revealPanel(node) {
const panel = node?.closest?.('.panel') || node;
const workbenchSection = panel?.closest?.('[data-workbench-section]') || panel;
if (workbenchSection?.dataset?.workbenchSection) {
activateWorkbenchSection(workbenchSection.dataset.workbenchSection, {
scrollToTop: false,
persist: true,
updateHash: true,
});
}
if (panel && typeof panel.scrollIntoView === 'function') {
panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
function loadAssistantHistoryKindFilter() {
try {
return window.localStorage?.getItem('assistantHistoryKindFilter') || '';
} catch {
return '';
}
}
function persistAssistantHistoryKindFilter(value) {
assistantHistoryKindFilter = value || 'all';
try {
window.localStorage?.setItem('assistantHistoryKindFilter', assistantHistoryKindFilter);
} catch {
// no-op
}
}
function loadAssistantDigestPreferenceMode() {
try {
return window.localStorage?.getItem('assistantDigestPreferenceMode') || '';
} catch {
return '';
}
}
function persistAssistantDigestPreferenceMode(value) {
assistantDigestPreferenceMode = value || 'all_reminders';
try {
window.localStorage?.setItem('assistantDigestPreferenceMode', assistantDigestPreferenceMode);
} catch {
// no-op
}
}
function loadAssistantDigestProfileKey() {
try {
return window.localStorage?.getItem('assistantDigestProfileKey') || '';
} catch {
return '';
}
}
function persistAssistantDigestProfileKey(value) {
assistantDigestProfileKey = value || 'local_operator';
try {
window.localStorage?.setItem('assistantDigestProfileKey', assistantDigestProfileKey);
} catch {
// no-op
}
}
async function persistAssistantDigestPreferenceServer({ profileKey, digestMode, preferredHistoryKind, importanceThreshold = 70, payload = null }) {
try {
const response = await postJson('/trading/alerts/digest-preferences', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: profileKey || assistantDigestProfileKey || 'local_operator',
digest_mode: digestMode || 'all_reminders',
preferred_history_kind: preferredHistoryKind || null,
importance_threshold: Number(importanceThreshold || 70),
payload: {
source: 'decision_assistant_workbench',
...(payload || {}),
},
});
persistAssistantDigestProfileKey(profileKey || assistantDigestProfileKey || 'local_operator');
return response;
} catch {
// no-op
return null;
}
}
async function createAssistantPreferenceProfile({ profileKey, profileLabel, sourceProfileKey = null, draft = null }) {
return postJson('/trading/alerts/digest-preferences/profiles', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: profileKey || null,
profile_label: profileLabel || null,
source_profile_key: sourceProfileKey || null,
digest_mode: draft?.digest_mode || null,
preferred_history_kind: draft?.preferred_history_kind === 'all' ? null : (draft?.preferred_history_kind || null),
importance_threshold: draft?.importance_threshold || null,
payload: draft ? {
profile_label: draft.profile_label || profileLabel || null,
history_window_hours: draft.history_window_hours || 24,
importance_templates: { ...(draft.importance_templates || {}) },
} : null,
});
}
async function renameAssistantPreferenceProfile({ profileKey, newProfileKey = null, profileLabel = null }) {
return postJson(`/trading/alerts/digest-preferences/profiles/${encodeURIComponent(profileKey)}/rename`, {
instrument_id: Number(instrumentIdInput.value || 1),
new_profile_key: newProfileKey || null,
profile_label: profileLabel || null,
});
}
async function deleteAssistantPreferenceProfile(profileKey) {
return postJson(`/trading/alerts/digest-preferences/profiles/${encodeURIComponent(profileKey)}/delete`, {
instrument_id: Number(instrumentIdInput.value || 1),
});
}
async function persistAssistantArchiveBaselinesServer({ profileKey, digestSnapshotId = undefined, workflowSnapshotId = undefined }) {
return postJson('/trading/archive-baselines', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: profileKey || assistantDigestProfileKey || 'local_operator',
...(digestSnapshotId !== undefined ? { digest_snapshot_id: digestSnapshotId } : {}),
...(workflowSnapshotId !== undefined ? { workflow_snapshot_id: workflowSnapshotId } : {}),
});
}
async function persistWorkflowArchiveBridgeStateServer({ summary, exportPayload, profileKey }) {
const digestSurface = summary?.digest_surface || {};
const digestProfile = digestSurface.digest_preference_profile || {};
const saved = await persistAssistantDigestPreferenceServer({
profileKey: profileKey || assistantDigestProfileKey || 'local_operator',
digestMode: assistantPreferenceDraft?.digest_mode || digestProfile.persisted_digest_mode || 'all_reminders',
preferredHistoryKind: assistantPreferenceDraft?.preferred_history_kind === 'all'
? null
: (assistantPreferenceDraft?.preferred_history_kind || digestProfile.preferred_history_kind || null),
importanceThreshold: assistantPreferenceDraft?.importance_threshold || digestProfile.importance_threshold || 70,
payload: {
profile_label: assistantPreferenceDraft?.profile_label || digestProfile.profile_label || profileKey || 'local_operator',
history_window_hours: assistantPreferenceDraft?.history_window_hours || digestProfile.history_window_hours || 24,
importance_templates: { ...((assistantPreferenceDraft && assistantPreferenceDraft.importance_templates) || {}) },
archive_defaults: { ...((assistantPreferenceDraft && assistantPreferenceDraft.archive_defaults) || digestProfile.archive_defaults || {}) },
workflow_bridge_state: {
handoff_packet_starter: exportPayload?.handoff_packet_starter || {},
replay_note_bridge_summary: exportPayload?.replay_note_bridge_summary || {},
artifact_bundle_summary: exportPayload?.artifact_bundle_summary || {},
query_context: {
profile_key: assistantWorkflowArchiveState.profile_key || profileKey || assistantDigestProfileKey || 'local_operator',
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
},
updated_ts: new Date().toISOString(),
},
},
});
if (saved) {
assistantPreferenceDraft = {
...(assistantPreferenceDraft || {}),
archive_defaults: { ...((assistantPreferenceDraft && assistantPreferenceDraft.archive_defaults) || digestProfile.archive_defaults || {}) },
};
}
return saved;
}
async function persistWorkflowArchiveCompareWritebackServer({ profileKey, compare, author = 'local_operator' }) {
return postJson('/trading/workflow-archive/compare-writeback', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: profileKey || assistantDigestProfileKey || 'local_operator',
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
left_id: compare?.left?.snapshot_id ?? assistantWorkflowArchiveState.selected_left_id ?? null,
right_id: compare?.right?.snapshot_id ?? assistantWorkflowArchiveState.selected_right_id ?? null,
current_session: assistantWorkflowArchiveState.current_session || compare?.left?.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || compare?.left?.next_phase || '',
query_text: assistantWorkflowArchiveState.query_text || '',
author,
note_scope: 'workflow_compare',
});
}
function loadAssistantScanHandoffMarker() {
try {
const raw = window.localStorage?.getItem('assistantScanHandoffMarker');
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
}
function loadAssistantFocusCandidateId() {
try {
return window.localStorage?.getItem('assistantFocusCandidateId') || '';
} catch {
return '';
}
}
function persistAssistantFocusCandidateId(value) {
assistantFocusCandidateId = value == null ? '' : String(value);
try {
if (assistantFocusCandidateId) {
window.localStorage?.setItem('assistantFocusCandidateId', assistantFocusCandidateId);
} else {
window.localStorage?.removeItem('assistantFocusCandidateId');
}
} catch {
// no-op
}
}
async function persistAssistantFocusCandidateServer(value) {
try {
await postJson('/trading/assistant-focus', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestProfileKey || 'local_operator',
candidate_id: value == null ? null : Number(value),
});
} catch {
// no-op
}
}
async function fetchAssistantDigestArchive(overrides = {}) {
const append = Boolean(overrides.append);
const nextState = {
...assistantDigestArchiveState,
profile_key: assistantDigestArchiveState.profile_key || assistantDigestProfileKey || 'local_operator',
...overrides,
};
delete nextState.append;
const params = {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: nextState.profile_key || assistantDigestProfileKey || 'local_operator',
profile_scope: nextState.profile_scope || 'selected_profile',
query_preset: nextState.query_preset || null,
preferred_history_kind: nextState.preferred_history_kind || null,
digest_mode: nextState.digest_mode || null,
query_text: nextState.query_text || null,
created_after: nextState.created_after || null,
created_before: nextState.created_before || null,
limit: Number(nextState.limit || 12),
offset: append ? Number(assistantDigestArchiveState.next_offset || 0) : 0,
};
assistantDigestArchiveState = {
...nextState,
limit: params.limit,
profile_key: params.profile_key,
profile_scope: params.profile_scope,
query_preset: params.query_preset || '',
};
window.__assistantDigestArchiveQuery = params;
const response = await fetchJson(`/trading/alerts/digest-history-archive?${queryString(params)}`);
if (append && window.__assistantDigestArchiveResponse?.items?.length) {
response.items = [...(window.__assistantDigestArchiveResponse.items || []), ...(response.items || [])];
response.item_count = response.items.length;
}
assistantDigestArchiveState.next_offset = Number(response.next_offset || 0);
window.__assistantDigestArchiveResponse = response;
if (assistantDigestArchiveState.selected_left_id && assistantDigestArchiveState.selected_right_id) {
window.__assistantDigestArchiveCompare = await fetchJson(`/trading/alerts/digest-history-archive/compare?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestArchiveState.profile_key || assistantDigestProfileKey || 'local_operator',
profile_scope: assistantDigestArchiveState.profile_scope || 'selected_profile',
query_preset: assistantDigestArchiveState.query_preset || '',
left_id: assistantDigestArchiveState.selected_left_id,
right_id: assistantDigestArchiveState.selected_right_id,
})}`);
} else {
window.__assistantDigestArchiveCompare = await fetchJson(`/trading/alerts/digest-history-archive/compare?${queryString(params)}`);
}
}
async function fetchAssistantWorkflowArchive(overrides = {}) {
const append = Boolean(overrides.append);
const nextState = {
...assistantWorkflowArchiveState,
profile_key: assistantWorkflowArchiveState.profile_key || assistantDigestProfileKey || 'local_operator',
...overrides,
};
delete nextState.append;
const params = {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: nextState.profile_key || assistantDigestProfileKey || 'local_operator',
profile_scope: nextState.profile_scope || 'selected_profile',
query_preset: nextState.query_preset || null,
current_session: nextState.current_session || null,
next_phase: nextState.next_phase || null,
next_artifact_kind: nextState.next_artifact_kind || null,
query_text: nextState.query_text || null,
created_after: nextState.created_after || null,
created_before: nextState.created_before || null,
limit: Number(nextState.limit || 12),
offset: append ? Number(assistantWorkflowArchiveState.next_offset || 0) : 0,
};
assistantWorkflowArchiveState = {
...nextState,
limit: params.limit,
profile_key: params.profile_key,
profile_scope: params.profile_scope,
query_preset: params.query_preset || '',
};
window.__assistantWorkflowArchiveQuery = params;
const response = await fetchJson(`/trading/workflow-archive?${queryString(params)}`);
if (append && window.__assistantWorkflowArchiveResponse?.items?.length) {
response.items = [...(window.__assistantWorkflowArchiveResponse.items || []), ...(response.items || [])];
response.item_count = response.items.length;
}
assistantWorkflowArchiveState.next_offset = Number(response.next_offset || 0);
window.__assistantWorkflowArchiveResponse = response;
if (assistantWorkflowArchiveState.selected_left_id && assistantWorkflowArchiveState.selected_right_id) {
window.__assistantWorkflowArchiveCompare = await fetchJson(`/trading/workflow-archive/compare?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || assistantDigestProfileKey || 'local_operator',
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
left_id: assistantWorkflowArchiveState.selected_left_id,
right_id: assistantWorkflowArchiveState.selected_right_id,
})}`);
} else {
window.__assistantWorkflowArchiveCompare = await fetchJson(`/trading/workflow-archive/compare?${queryString(params)}`);
}
}
function selectAssistantDigestArchiveSnapshot(side, snapshotId) {
if (side === 'left') assistantDigestArchiveState.selected_left_id = snapshotId;
if (side === 'right') assistantDigestArchiveState.selected_right_id = snapshotId;
}
function selectAssistantWorkflowArchiveSnapshot(side, snapshotId) {
if (side === 'left') assistantWorkflowArchiveState.selected_left_id = snapshotId;
if (side === 'right') assistantWorkflowArchiveState.selected_right_id = snapshotId;
}
function persistAssistantScanHandoffMarker(marker) {
assistantScanHandoffMarker = marker || null;
try {
if (assistantScanHandoffMarker) {
window.localStorage?.setItem('assistantScanHandoffMarker', JSON.stringify(assistantScanHandoffMarker));
} else {
window.localStorage?.removeItem('assistantScanHandoffMarker');
}
} catch {
// no-op
}
}
function buildAssistantPreferenceDraft(summary) {
const digestSurface = summary?.digest_surface || {};
const profile = digestSurface.digest_preference_profile || {};
const templates = {};
(profile.importance_templates || []).forEach((item) => {
if (item?.template) templates[item.template] = Number(item.threshold || item.default_threshold || 0);
});
return {
profile_key: profile.selected_profile_key || assistantDigestProfileKey || 'local_operator',
profile_label: profile.profile_label || 'Local operator',
digest_mode: profile.persisted_digest_mode || profile.default_mode || 'all_reminders',
preferred_history_kind: profile.preferred_history_kind || 'all',
importance_threshold: Number(profile.importance_threshold || 70),
history_window_hours: Number(profile.history_window_hours || 24),
importance_templates: templates,
focus_candidate_id: profile.focus_candidate_id ?? summary?.focus_workspace_context?.focus_candidate_id ?? null,
archive_defaults: profile.archive_defaults || {
digest: { profile_scope: 'selected_profile', query_preset: '' },
workflow: { profile_scope: 'selected_profile', query_preset: '' },
},
};
}
function buildAssistantPreferenceDraftVersion(summary) {
const profile = summary?.digest_surface?.digest_preference_profile || {};
return `${profile.selected_profile_key || 'local_operator'}:${profile.persisted_updated_ts || 'none'}`;
}
function ensureAssistantPreferenceDraft(summary) {
const nextDraft = buildAssistantPreferenceDraft(summary);
const nextVersion = buildAssistantPreferenceDraftVersion(summary);
if (!assistantPreferenceDraft || assistantPreferenceDraft.profile_key !== nextDraft.profile_key) {
assistantPreferenceDraft = nextDraft;
assistantPreferenceDraftDirty = false;
assistantPreferenceDraftVersion = nextVersion;
return;
}
if (!assistantPreferenceDraftDirty && assistantPreferenceDraftVersion !== nextVersion) {
assistantPreferenceDraft = nextDraft;
assistantPreferenceDraftVersion = nextVersion;
}
}
function updateAssistantPreferenceDraft(patch = {}) {
assistantPreferenceDraft = {
...(assistantPreferenceDraft || {}),
...(patch || {}),
};
assistantPreferenceDraftDirty = true;
}
function updateAssistantPreferenceTemplateDraft(template, threshold) {
const nextTemplates = {
...((assistantPreferenceDraft && assistantPreferenceDraft.importance_templates) || {}),
};
nextTemplates[template] = Number(threshold || 0);
updateAssistantPreferenceDraft({ importance_templates: nextTemplates });
}
function mergeAssistantArchiveDefaults(summary, patch = {}) {
const profile = summary?.digest_surface?.digest_preference_profile || {};
const currentDefaults = {
digest: { profile_scope: 'selected_profile', query_preset: '' },
workflow: { profile_scope: 'selected_profile', query_preset: '' },
...((assistantPreferenceDraft && assistantPreferenceDraft.archive_defaults) || profile.archive_defaults || {}),
};
return {
...currentDefaults,
...(patch || {}),
};
}
function resetAssistantPreferenceDraftToServer(summary) {
assistantPreferenceDraft = buildAssistantPreferenceDraft(summary);
assistantPreferenceDraftDirty = false;
assistantPreferenceDraftVersion = buildAssistantPreferenceDraftVersion(summary);
}
function resetAssistantPreferenceDraftToDefaults(summary) {
const profile = summary?.digest_surface?.digest_preference_profile || {};
const templates = {};
(profile.importance_templates || []).forEach((item) => {
if (item?.template) templates[item.template] = Number(item.default_threshold || item.threshold || 0);
});
assistantPreferenceDraft = {
...(assistantPreferenceDraft || buildAssistantPreferenceDraft(summary)),
digest_mode: 'all_reminders',
preferred_history_kind: 'all',
importance_threshold: 70,
history_window_hours: 24,
importance_templates: templates,
};
assistantPreferenceDraftDirty = true;
}
function snoozeAssistantScanHandoffMarker(seconds, reason = 'operator_snooze') {
if (!assistantScanHandoffMarker) return;
const duration = Math.max(60, Number(seconds || 1800));
persistAssistantScanHandoffMarker({
...assistantScanHandoffMarker,
snoozed_until: new Date(Date.now() + duration * 1000).toISOString(),
snooze_reason: reason,
});
}
function normalizeAssistantSectionId(title) {
return String(title || '')
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
}
function revealAssistantSection(sectionId) {
if (!decisionAssistantPanel) return;
activateWorkbenchSection('decision-assistant', {
scrollToTop: false,
persist: true,
updateHash: true,
});
const aliases = {
watchlist: 'watchlist-review-now',
notes: 'review-entry',
replay: 'setup-replay',
};
const normalized = aliases[sectionId] || sectionId;
let target = decisionAssistantPanel.querySelector(`[data-assistant-section="${normalized}"]`);
if (!target && normalized.startsWith('watchlist')) {
target = decisionAssistantPanel.querySelector('[data-assistant-section^="watchlist"]');
}
if (target && typeof target.scrollIntoView === 'function') {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
function scanCardActionLabel(sectionId) {
if (sectionId === 'review-entry') return 'Open Review';
if (sectionId === 'digest') return 'Open Digest';
if (sectionId === 'external-context') return 'Open Context';
return 'Open';
}
function filterAssistantReminders(reminders, mode) {
if (!Array.isArray(reminders) || !reminders.length) return [];
if (mode === 'high_value_only') {
return reminders.filter((item) => Boolean(item.high_value));
}
if (mode === 'risk_first') {
return reminders.filter((item) =>
item.source === 'no_trade_reason_items'
|| item.importance_template === 'risk_first_change'
|| item.severity === 'high'
);
}
return reminders;
}
function getAssistantFocusContext(summary = window.__latestDecisionAssistantSummary || null) {
const assistantSummary = summary || {};
const focusWorkspace = assistantSummary.focus_workspace_context || {};
const tiers = assistantSummary.candidate_watchlist_tiers || {};
const allWatchlistItems = [
...(tiers.review_now || []),
...(tiers.strong_watch || []),
...(tiers.soft_watch || []),
...(tiers.archive_only || []),
];
const focusCandidate = allWatchlistItems.find((item) => String(item.candidate_id || '') === String(focusWorkspace.focus_candidate_id || ''));
return {
candidate_id: focusCandidate?.candidate_id ?? focusWorkspace.focus_candidate_id ?? null,
session_code: focusCandidate?.session_code ?? focusWorkspace.focus_session_code ?? null,
model_code: focusCandidate?.model_code ?? focusWorkspace.focus_model_code ?? null,
title: focusCandidate?.title ?? focusWorkspace.focus_title ?? null,
detail: focusCandidate?.detail ?? focusWorkspace.focus_detail ?? null,
};
}
function buildOperatorNoteTags(baseTags = [], context = null) {
const tags = [...(Array.isArray(baseTags) ? baseTags : [])];
if (context?.candidate_id != null) tags.push(`candidate:${context.candidate_id}`);
if (context?.session_code) tags.push(`session:${context.session_code}`);
if (context?.model_code) tags.push(`model:${context.model_code}`);
return Array.from(new Set(tags.filter(Boolean)));
}
function prefillOperatorNote(body, context = null) {
const resolvedContext = context || getAssistantFocusContext();
assistantOperatorNoteDraft = {
body: body || '',
context: resolvedContext,
};
revealPanel(operatorConsolePanel);
const textarea = operatorConsolePanel.querySelector('textarea');
if (textarea) {
textarea.value = body || '';
textarea.focus();
}
}
function buildWorkflowArchiveBridgeContext(item, bridgeMode = 'note') {
if (!item) return null;
return {
bridge_mode: bridgeMode,
snapshot_id: item.snapshot_id ?? null,
session_code: item.current_session || null,
model_code: null,
next_phase: item.next_phase || null,
next_artifact_kind: item.next_artifact_kind || null,
workflow_body: item.workflow_body || '',
next_artifact_prompt: item.next_artifact_prompt || '',
phase_briefs: Array.isArray(item.phase_briefs) ? item.phase_briefs : [],
created_ts: item.created_ts || null,
};
}
function setWorkflowArchiveBridgeContext(context) {
assistantWorkflowArchiveBridgeContext = context || null;
}
function buildWorkflowArchiveBridgeNote(item) {
const phaseLines = (item.phase_briefs || [])
.map((row) => `- ${row.phase || 'phase'}: ${row.archive_body || row.detail || 'n/a'}`)
.join('\n');
return [
`[workflow-archive] Snapshot #${item.snapshot_id ?? 'n/a'} | ${item.current_session || 'n/a'} -> ${item.next_phase || 'workflow'}`,
item.workflow_body || '',
item.next_artifact_prompt ? `Next prompt: ${item.next_artifact_prompt}` : '',
phaseLines ? `Phase briefs:\n${phaseLines}` : '',
].filter(Boolean).join('\n\n');
}
function buildWorkflowArchiveCompareReplayNote(compare) {
const left = compare?.left || {};
const right = compare?.right || {};
const changed = (compare?.phase_changes || []).filter((item) => item.changed);
const changedLabels = changed.map((item) => item.phase || 'phase').join(', ') || 'none';
return [
`[workflow-compare] Snapshot #${left.snapshot_id ?? 'n/a'} vs #${right.snapshot_id ?? 'n/a'}`,
`Session/Phase: ${left.current_session || 'n/a'} -> ${left.next_phase || 'n/a'}`,
`Changed phases: ${changedLabels}`,
`Artifact delta: ${compare?.count_delta?.artifact_count ?? 0} | Ready delta: ${compare?.count_delta?.ready_for_handoff_count ?? 0} | Update delta: ${compare?.count_delta?.needs_update_count ?? 0}`,
compare?.summary || '',
].filter(Boolean).join('\n\n');
}
function appendSectionTitle(container, title) {
const element = createElement('div', 'assistant-section-title', title);
element.dataset.assistantSection = normalizeAssistantSectionId(title);
container.appendChild(element);
}
function createElement(tag, className, text) {
const element = document.createElement(tag);
if (className) element.className = className;
if (text != null) setText(element, text);
return element;
}
function formatNumber(value, digits = 2) {
if (value == null || value === '') return 'n/a';
const number = Number(value);
if (!Number.isFinite(number)) return 'n/a';
return number.toFixed(digits);
}
function formatPercent(value) {
if (value == null) return 'n/a';
const number = Number(value);
if (!Number.isFinite(number)) return 'n/a';
return `${(number * 100).toFixed(1)}%`;
}
function formatTimestamp(value) {
if (!value) return 'n/a';
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return String(value);
}
return date.toLocaleString();
}
function formatDurationSeconds(value) {
const seconds = Number(value);
if (!Number.isFinite(seconds) || seconds < 0) return 'n/a';
if (seconds < 60) return `${Math.round(seconds)}s`;
if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
return `${(seconds / 3600).toFixed(1)}h`;
}
function resolveAssistantHandoffAge(marker, fallbackStaleAfterSeconds = 3600) {
if (!marker?.saved_ts) {
return {
status: 'none',
stale: false,
snoozed: false,
age_seconds: null,
age_label: 'n/a',
snooze_label: 'n/a',
warning: 'No persisted handoff marker.',
};
}
const savedAt = new Date(marker.saved_ts);
if (Number.isNaN(savedAt.getTime())) {
return {
status: 'unknown_age',
stale: true,
snoozed: false,
age_seconds: null,
age_label: 'unknown',
snooze_label: 'n/a',
warning: 'Saved handoff timestamp is not readable; reopen before reuse.',
};
}
const snoozedUntil = marker.snoozed_until ? new Date(marker.snoozed_until) : null;
const snoozed = Boolean(snoozedUntil && !Number.isNaN(snoozedUntil.getTime()) && snoozedUntil.getTime() > Date.now());
const staleAfterSeconds = Number(marker.stale_after_seconds || marker.handoff_stale_after_seconds || fallbackStaleAfterSeconds || 3600);
const ageSeconds = Math.max(0, Math.round((Date.now() - savedAt.getTime()) / 1000));
const stale = ageSeconds > staleAfterSeconds;
const aging = ageSeconds > staleAfterSeconds / 2;
return {
status: snoozed ? 'snoozed_handoff' : (stale ? 'stale_handoff' : (aging ? 'aging_handoff' : 'fresh_handoff')),
stale,
snoozed,
age_seconds: ageSeconds,
age_label: formatDurationSeconds(ageSeconds),
stale_after_seconds: staleAfterSeconds,
snoozed_until: marker.snoozed_until || null,
snooze_label: snoozed ? formatTimestamp(marker.snoozed_until) : 'n/a',
warning: snoozed
? `Saved handoff is snoozed until ${formatTimestamp(marker.snoozed_until)}.`
: stale
? (marker.stale_warning || 'Saved handoff is stale; reopen the target section before reuse.')
: (marker.stale_warning || 'Saved handoff is still inside its freshness window.'),
};
}
function formatList(values, emptyText = 'n/a') {
if (!Array.isArray(values) || values.length === 0) return emptyText;
return values.map((value) => String(value)).join(', ');
}
function formatJsonInline(value, emptyText = 'n/a') {
if (value == null) return emptyText;
if (Array.isArray(value) && value.length === 0) return emptyText;
if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length === 0) return emptyText;
return JSON.stringify(value);
}
function statusClass(status) {
const raw = String(status || 'unknown').toLowerCase().replace(/[^a-z0-9]+/g, '_');
return `status-pill status-${raw || 'unknown'}`;
}
function buildStatusPill(status) {
return createElement('span', statusClass(status), status || 'unknown');
}
function buildMetricCard(label, value, detail = '') {
const card = createElement('div', 'card');
card.appendChild(createElement('div', 'metric', label));
card.appendChild(createElement('div', 'value-small', value));
if (detail) card.appendChild(createElement('div', 'metric', detail));
return card;
}
function buildInfoGrid(entries) {
const grid = createElement('div', 'info-grid');
entries.forEach(([label, value]) => {
const row = createElement('div', 'info-row');
row.appendChild(createElement('div', 'metric', label));
row.appendChild(createElement('div', 'info-value', value == null || value === '' ? 'n/a' : String(value)));
grid.appendChild(row);
});
return grid;
}
function buildActionBar(actions) {
const bar = createElement('div', 'actions');
actions
.filter((action) => action && typeof action.onClick === 'function')
.forEach((action) => {
const button = createElement('button', '', action.label);
button.type = 'button';
button.addEventListener('click', action.onClick);
bar.appendChild(button);
});
return bar;
}
function buildItemCard(title, status, entries, actions = [], detail = '') {
const card = createElement('div', 'card');
const header = createElement('div', 'card-header');
header.appendChild(createElement('strong', '', title));
header.appendChild(buildStatusPill(status));
card.appendChild(header);
card.appendChild(buildInfoGrid(entries));
if (detail) card.appendChild(createElement('div', 'metric card-detail', detail));
if (actions.length) card.appendChild(buildActionBar(actions));
return card;
}
function getSearchText() {
return String(searchTextInput.value || '').trim().toLowerCase();
}
function updateActiveFilters() {
const active = [];
const executionStatus = executionStatusFilterInput.value || 'all';
const session = sessionFilterInput.value || 'all';
const search = getSearchText();
const trustClass = trustClassFilterInput.value || 'all';
if (executionStatus !== 'all') active.push(`execution=${executionStatus}`);
if (session !== 'all') active.push(`session=${session}`);
if (trustClass !== 'all') active.push(`trust=${trustClass}`);
if (search) active.push(`search=${search}`);
setText(activeFilters, `Filters: ${active.length ? active.join(', ') : 'none'}`);
}
function filterBySearch(items, projector) {
const search = getSearchText();
if (!search) return items;
return items.filter((item) => String(projector(item)).toLowerCase().includes(search));
}
function filterExecutions(items) {
const statusFilter = executionStatusFilterInput.value || 'all';
const sessionFilter = sessionFilterInput.value || 'all';
return filterBySearch(
items.filter((item) => (statusFilter === 'all' || item.execution_status === statusFilter)
&& (sessionFilter === 'all' || item.session_code === sessionFilter)),
(item) => [
item.execution_id,
item.execution_status,
item.side,
item.session_code,
item.close_reason,
item.ai_explanation,
...(item.error_tags || []),
].join(' ')
);
}
function filterBySession(items, accessor) {
const sessionFilter = sessionFilterInput.value || 'all';
if (sessionFilter === 'all') return items;
return items.filter((item) => String(accessor(item) || '') === sessionFilter);
}
function queryString(params) {
const search = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value == null || value === '') return;
search.set(key, String(value));
});
return search.toString();
}
async function runAction(url, body = {}) {
try {
await postJson(url, body);
await refreshDashboard();
} catch (error) {
showErrorPanel(String(error));
}
}
async function recordShadowPaperObservation(operatorAgreement = 'pending') {
await runAction('/trading/shadow-paper/observe', {
instrument_id: Number(instrumentIdInput.value || 1),
timeframe: '1m',
session_code: sessionFilterInput.value === 'all' ? null : sessionFilterInput.value,
operator_agreement: operatorAgreement,
operator_note: operatorAgreement === 'pending'
? 'Daily shadow observation captured from cockpit.'
: `Operator marked shadow observation as ${operatorAgreement}.`,
created_by: 'local_operator',
});
}
function openExternalContextLink(url) {
if (!url) return;
window.open(url, '_blank', 'noopener,noreferrer');
}
async function persistExternalContextSurfaceHistory(meta = {}) {
try {
return await postJson('/trading/external-context-surface-history', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestProfileKey || 'local_operator',
surface_id: meta.surface_id || meta.title || 'external_surface',
title: meta.title || meta.surface_id || 'external surface',
source_group: meta.source_group || 'external_context',
selection_kind: meta.selection_kind || 'target_url',
target_url: meta.target_url || '',
prompt: meta.prompt || '',
});
} catch {
return null;
}
}
async function acknowledgeExternalContextSurfaceHistory(meta = {}) {
try {
return await postJson('/trading/external-context-surface-history/acknowledge', {
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestProfileKey || 'local_operator',
surface_id: meta.surface_id || '',
selected_ts: meta.selected_ts || '',
acknowledged_by: meta.acknowledged_by || 'local_operator',
note: meta.note || '',
});
} catch {
return null;
}
}
function matchesSurfaceResolutionFilter(item, filterId) {
const normalized = String(filterId || 'all');
if (normalized === 'all') return true;
if (normalized === 'with_note') return Boolean(String(item?.revisit_ack_note || '').trim());
if (normalized === 'without_note') return !String(item?.revisit_ack_note || '').trim();
if (normalized.startsWith('group:')) return String(item?.source_group || '') === normalized.slice(6);
if (normalized.startsWith('ack:')) return String(item?.revisit_acknowledged_by || '') === normalized.slice(4);
return true;
}
function getDefaultSurfaceResolutionFilterOptions(summary = {}) {
const entryCount = Number(summary?.resolution_history_count ?? 0);
const noteCount = Number(summary?.resolution_filter_summary?.note_count ?? 0);
const noteGapCount = Number(summary?.resolution_filter_summary?.note_gap_count ?? 0);
return [
{ filter_id: 'all', label: `All Resolved (${entryCount})`, count: entryCount },
{ filter_id: 'with_note', label: `With Resolution Note (${noteCount})`, count: noteCount },
{ filter_id: 'without_note', label: `Without Resolution Note (${noteGapCount})`, count: noteGapCount },
];
}
function openTrackedExternalContextLink(url, meta = null) {
if (!url) return;
openExternalContextLink(url);
if (meta) {
persistExternalContextSurfaceHistory({ ...meta, target_url: meta.target_url || url })
.then((result) => {
if (result) {
refreshDashboard().catch(() => {});
}
})
.catch(() => {});
}
}
async function saveOperatorTemplateNote(template) {
const focusContext = getAssistantFocusContext();
try {
await postJson('/trading/operator-notes', {
instrument_id: Number(instrumentIdInput.value || 1),
note_scope: template.note_scope || 'workbench',
author: 'assistant_template',
body: template.body || '',
session_code: focusContext.session_code || (sessionFilterInput.value === 'all' ? null : sessionFilterInput.value),
candidate_id: focusContext.candidate_id,
tags: buildOperatorNoteTags(Array.isArray(template.tags) ? template.tags : ['assistant-template'], focusContext),
});
await refreshDashboard();
} catch (error) {
showErrorPanel(String(error));
}
}
async function saveOperatorTemplateFeedback(template, outcome) {
const templateId = String(template?.template_id || 'template');
const normalizedOutcome = String(outcome || 'useful').toLowerCase().replace(/[^a-z0-9_-]+/g, '_');
const templateTag = templateId.replace(/_/g, '-');
const focusContext = getAssistantFocusContext();
try {
await postJson('/trading/operator-notes', {
instrument_id: Number(instrumentIdInput.value || 1),
note_scope: template?.note_scope || 'workbench',
author: 'assistant_template',
body: `[template-feedback] ${templateId} | outcome:${normalizedOutcome} | ${template?.label || 'template'}`,
session_code: focusContext.session_code || (sessionFilterInput.value === 'all' ? null : sessionFilterInput.value),
candidate_id: focusContext.candidate_id,
tags: buildOperatorNoteTags(['assistant-template', 'template-feedback', templateTag, `template:${templateId}`, `outcome:${normalizedOutcome}`], focusContext),
});
await refreshDashboard();
} catch (error) {
showErrorPanel(String(error));
}
}
function renderHealth(health) {
setText(
healthStatus,
[
health?.app || 'ai-ict',
health?.database_configured ? 'db ready' : 'db missing',
health?.session_timezone || 'timezone unknown',
].join(' | ')
);
}
function renderOverview(weeklyReview, candidates, tickets, executions) {
clearNode(overviewCards);
const openExecutions = executions.filter((item) => item.execution_status === 'open');
const confirmedTickets = tickets.filter((item) => item.status === 'confirmed');
const executableCandidates = candidates.filter((item) => item.executable);
const cards = [
buildMetricCard('Executable Candidates', String(executableCandidates.length), 'ready to ticket'),
buildMetricCard('Confirmed Tickets', String(confirmedTickets.length), 'human confirmed'),
buildMetricCard('Open Positions', String(openExecutions.length), 'live management load'),
buildMetricCard('Framework Rate', formatPercent(weeklyReview?.framework_execution_rate), 'weekly execution discipline'),
buildMetricCard('Out-of-Model Rate', formatPercent(weeklyReview?.out_of_model_trade_rate), 'model drift'),
buildMetricCard('Risk Violations', String(weeklyReview?.risk_violation_count ?? 0), 'weekly count'),
];
cards.forEach((card) => overviewCards.appendChild(card));
}
function renderDecisionAssistant(summary) {
clearNode(decisionAssistantPanel);
decisionAssistantPanel.classList.add('assistant-dense');
window.__latestDecisionAssistantSummary = summary;
if (!summary || summary.status === 'unavailable') {
decisionAssistantPanel.appendChild(createElement('div', 'empty-state', 'Decision assistant summary unavailable.'));
return;
}
const evidence = summary.evidence_summary || {};
const traderModeSummary = summary.trader_mode_summary || null;
const scanSummaryCards = summary.scan_summary_cards || [];
const scanCompletionSummary = summary.scan_completion_summary || null;
const scanHandoffSummary = summary.scan_handoff_summary || null;
const workflowDigest = summary.workflow_digest || [];
const workflowRhythmSummary = summary.workflow_rhythm_summary || null;
const workflowSessionCompletionSummary = summary.workflow_session_completion_summary || null;
const assistantLoopQueue = summary.assistant_loop_queue || [];
const assistantLoopSummary = summary.assistant_loop_summary || null;
const opportunities = summary.top_opportunities || [];
const watchlistTiers = summary.candidate_watchlist_tiers || {};
const watchlistSummary = summary.candidate_watchlist_summary || {};
const noTradeItems = summary.no_trade_reason_items || [];
const evidenceChain = summary.evidence_chain || [];
const decisionTimeline = summary.decision_timeline || [];
const explanationDrilldown = summary.explanation_drilldown || [];
const reasonCitations = summary.reason_citations || [];
const learningRollup = summary.learning_rollup || null;
const externalContext = summary.external_context_summary || null;
const decisionSupportBoundarySummary = summary.decision_support_boundary_summary || null;
const decisionSupportPromotionSummary = summary.decision_support_promotion_summary || null;
const liveAnalysisAssistantSummary = summary.live_analysis_assistant_summary || null;
const readonlyLiveHealthSummary = summary.readonly_live_health_summary || liveAnalysisAssistantSummary?.health_summary || null;
const shadowPaperValidationSummary = summary.shadow_paper_validation_summary || null;
const reviewEntrypoints = summary.review_entrypoints || null;
const personalizedReminders = summary.personalized_reminders || [];
const digestHistoryPreview = summary.digest_history_preview || [];
const digestHistoryGroups = summary.digest_history_groups || [];
const digestSurface = summary.digest_surface || null;
const digestHistoryBrowser = summary.digest_history_browser || digestSurface?.history_browser || null;
const digestPreferenceProfile = digestSurface?.digest_preference_profile || null;
ensureAssistantPreferenceDraft(summary);
const selectedProfileKey = assistantDigestProfileKey
|| assistantPreferenceDraft?.profile_key
|| digestPreferenceProfile?.selected_profile_key
|| 'local_operator';
const digestArchiveData = window.__assistantDigestArchiveResponse?.instrument_id === Number(instrumentIdInput.value || 1)
? window.__assistantDigestArchiveResponse
: digestSurface?.digest_history_archive;
const digestArchiveCompare = window.__assistantDigestArchiveCompare?.status
? window.__assistantDigestArchiveCompare
: (digestSurface?.digest_archive_compare || summary.digest_archive_compare || null);
const digestArchiveLongRangeSummary = digestArchiveData?.long_range_trend_summary || digestSurface?.digest_history_archive?.long_range_trend_summary || null;
const digestArchiveBaselineSummary = digestArchiveData?.baseline_pin_summary || digestSurface?.digest_history_archive?.baseline_pin_summary || null;
const digestArchiveSavedDefaults = digestPreferenceProfile?.archive_defaults?.digest || { profile_scope: 'selected_profile', query_preset: '' };
const digestArchiveRankedAggregation = digestArchiveData?.ranked_aggregation_summary || digestSurface?.digest_history_archive?.ranked_aggregation_summary || null;
const workflowArchiveData = window.__assistantWorkflowArchiveResponse?.instrument_id === Number(instrumentIdInput.value || 1)
? window.__assistantWorkflowArchiveResponse
: summary.workflow_artifact_summary?.workflow_history_archive;
const workflowArchiveCompare = window.__assistantWorkflowArchiveCompare?.status
? window.__assistantWorkflowArchiveCompare
: (summary.workflow_artifact_summary?.workflow_archive_compare || summary.workflow_archive_compare || null);
const workflowArchiveLongRangeSummary = workflowArchiveData?.long_range_trend_summary || summary.workflow_artifact_summary?.workflow_history_archive?.long_range_trend_summary || null;
const workflowArchiveBaselineSummary = workflowArchiveData?.baseline_pin_summary || summary.workflow_artifact_summary?.workflow_history_archive?.baseline_pin_summary || null;
const workflowArchiveSavedDefaults = digestPreferenceProfile?.archive_defaults?.workflow || { profile_scope: 'selected_profile', query_preset: '' };
const workflowArchiveRankedAggregation = workflowArchiveData?.ranked_aggregation_summary || summary.workflow_artifact_summary?.workflow_history_archive?.ranked_aggregation_summary || null;
const workflowArchiveOperationsSummary = workflowArchiveData?.operations_summary
|| summary.workflow_artifact_summary?.workflow_archive_operations_summary
|| summary.workflow_archive_operations_summary
|| null;
const workflowArchiveDriftReview = workflowArchiveData?.multi_day_drift_review
|| summary.workflow_artifact_summary?.workflow_archive_multi_day_drift_review
|| summary.workflow_archive_multi_day_drift_review
|| null;
const workflowArchiveBridgeSummary = workflowArchiveData?.bridge_summary
|| summary.workflow_artifact_summary?.workflow_archive_bridge_summary
|| summary.workflow_archive_bridge_summary
|| null;
const workflowArchiveBridgePersistenceSummary = summary.workflow_artifact_summary?.workflow_archive_bridge_persistence_summary
|| summary.workflow_archive_bridge_persistence_summary
|| null;
const archiveOperatorOverview = summary.archive_operator_overview || null;
const workflowArchiveDailyGroups = workflowArchiveData?.daily_groups || [];
const workflowArchiveSessionGroups = workflowArchiveData?.session_groups || [];
const workflowArchiveBridgeContext = assistantWorkflowArchiveBridgeContext;
const setupLearningRollup = summary.setup_learning_rollup || null;
const focusWorkspaceContext = summary.focus_workspace_context || null;
if (!assistantDigestProfileKey && digestPreferenceProfile?.selected_profile_key) {
persistAssistantDigestProfileKey(digestPreferenceProfile.selected_profile_key);
}
const continuousWorkspaceRail = summary.continuous_workspace_rail || [];
const continuousWorkspaceSummary = summary.continuous_workspace_summary || null;
const workspaceContinuityHandoff = summary.workspace_continuity_handoff || null;
const effectiveDigestPreferenceMode = assistantPreferenceDraft?.digest_mode
|| assistantDigestPreferenceMode
|| digestPreferenceProfile?.persisted_digest_mode
|| digestPreferenceProfile?.default_mode
|| 'all_reminders';
const activeHistoryFilter = assistantPreferenceDraft?.preferred_history_kind
|| assistantHistoryKindFilter
|| digestPreferenceProfile?.preferred_history_kind
|| 'all';
const visibleReminders = filterAssistantReminders(personalizedReminders, effectiveDigestPreferenceMode);
const reminderCards = visibleReminders.length ? visibleReminders : personalizedReminders;
const savedHandoffAge = resolveAssistantHandoffAge(assistantScanHandoffMarker, scanHandoffSummary?.default_stale_after_seconds);
const allWatchlistItems = [
...(watchlistTiers.review_now || []),
...(watchlistTiers.strong_watch || []),
...(watchlistTiers.soft_watch || []),
...(watchlistTiers.archive_only || []),
];
const resolvedFocusCandidate = allWatchlistItems.find((item) => String(item.candidate_id || '') === String(assistantFocusCandidateId || ''))
|| allWatchlistItems.find((item) => String(item.candidate_id || '') === String(focusWorkspaceContext?.focus_candidate_id || ''))
|| allWatchlistItems[0]
|| null;
const assistantSections = [
traderModeSummary ? { title: 'Trader Mode' } : null,
scanSummaryCards.length ? { title: 'Scan' } : null,
focusWorkspaceContext ? { title: 'Focus Workspace' } : null,
assistantLoopQueue.length ? { title: 'Loop Queue' } : null,
continuousWorkspaceRail.length ? { title: 'Workspace Rail' } : null,
workflowDigest.length ? { title: 'Workflow' } : null,
digestPreferenceProfile ? { title: 'Preferences' } : null,
digestSurface ? { title: 'Digest' } : null,
reviewEntrypoints ? { title: 'Review Entry' } : null,
opportunities.length ? { title: 'Opportunities' } : null,
evidenceChain.length ? { title: 'Evidence' } : null,
(watchlistTiers.review_now || []).length ? { title: 'Watchlist: Review Now' } : null,
noTradeItems.length ? { title: 'No-Trade Reasons' } : null,
setupLearningRollup ? { title: 'Setup Replay' } : null,
shadowPaperValidationSummary ? { title: 'Shadow Paper' } : null,
externalContext ? { title: 'External Context' } : null,
decisionTimeline.length ? { title: 'Timeline' } : null,
explanationDrilldown.length ? { title: 'Explain' } : null,
].filter(Boolean);
if (traderModeSummary) {
appendSectionTitle(decisionAssistantPanel, 'Trader Mode');
const opportunity = traderModeSummary.primary_opportunity || {};
const traderReadout = traderModeSummary.trader_readout || {};
const traderCard = buildItemCard(
'Trader Mode / Live Brief',
traderModeSummary.status_label || traderModeSummary.status || 'unknown',
[
['decision now', traderReadout.headline || traderModeSummary.primary_conclusion || 'n/a'],
['why no trade', traderReadout.why_no_trade || traderModeSummary.why_no_trade || 'analysis only'],
['watch next', traderReadout.watch_next || traderModeSummary.watch_next || traderModeSummary.next_action || 'continue_observation'],
['focus', `${opportunity.title || 'no clean opportunity'} / ${opportunity.tier || 'n/a'} / ${opportunity.status || 'n/a'}`],
['focus reason', traderReadout.focus_reason || traderModeSummary.focus_quality_explanation || 'n/a'],
['data state', traderReadout.data_state || `${traderModeSummary.data_confidence || 'unknown'} / ${traderModeSummary.status_color || 'unknown'}`],
['no candidate state', traderReadout.no_candidate_state || traderModeSummary.no_candidate_state || 'n/a'],
['trade action', traderModeSummary.primary_question_trade_action || 'not_a_buy_sell_instruction'],
],
(traderModeSummary.drilldown_sections || []).slice(0, 6).map((section) => ({
label: `Open ${section}`,
onClick: () => revealAssistantSection(normalizeAssistantSectionId(section)),
})),
traderModeSummary.operator_summary || ''
);
traderCard.classList.add('trader-mode-card');
traderCard.classList.add(`trader-mode-${traderModeSummary.status_color || 'unknown'}`);
decisionAssistantPanel.appendChild(traderCard);
}
if (scanSummaryCards.length) {
appendSectionTitle(decisionAssistantPanel, 'Scan');
const scanGrid = createElement('div', 'cards assistant-scan-grid');
scanSummaryCards.forEach((item) => {
const card = buildItemCard(
item.title || 'summary',
item.status || 'n/a',
[
['detail', item.detail || 'n/a'],
['context', item.context || 'n/a'],
['rank', String(item.rank ?? 'n/a')],
['scan step', item.is_next_scan_step ? 'next' : String(item.scan_step_index ?? 'n/a')],
['completion', item.completion_state || 'n/a'],
['completion hint', item.completion_hint || 'n/a'],
['handoff', item.handoff_status || 'n/a'],
['handoff marker', item.handoff_marker || 'n/a'],
['handoff prompt', item.handoff_prompt || 'n/a'],
['handoff stale after', formatDurationSeconds(item.handoff_stale_after_seconds)],
['handoff stale warning', item.handoff_stale_warning || 'n/a'],
['next step', item.transition_hint || 'n/a'],
],
[
...(item.target_section
? [{
label: item.action_label || scanCardActionLabel(item.target_section),
onClick: () => revealAssistantSection(item.target_section),
}]
: []),
item.handoff_marker
? {
label: 'Mark Handoff',
onClick: () => {
persistAssistantScanHandoffMarker({
marker: item.handoff_marker,
title: item.title || 'Scan',
target_section: item.target_section || '',
status: item.handoff_status || '',
stale_after_seconds: item.handoff_stale_after_seconds || scanHandoffSummary?.default_stale_after_seconds || 3600,
stale_warning: item.handoff_stale_warning || '',
saved_ts: new Date().toISOString(),
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}
: null,
].filter(Boolean)
);
if (item.target_section) {
card.classList.add('clickable-card');
card.addEventListener('click', () => revealAssistantSection(item.target_section));
}
if (item.emphasis) {
card.classList.add(`assistant-scan-${item.emphasis}`);
}
if (item.is_next_scan_step) {
card.classList.add('assistant-scan-next');
}
scanGrid.appendChild(card);
});
decisionAssistantPanel.appendChild(scanGrid);
if (scanCompletionSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['scan completion', scanCompletionSummary.status || 'idle'],
['open scan steps', String(scanCompletionSummary.open_count ?? 0)],
['blocked scan steps', String(scanCompletionSummary.blocked_count ?? 0)],
['refresh-needed steps', String(scanCompletionSummary.refresh_needed_count ?? 0)],
['ready steps', String(scanCompletionSummary.ready_count ?? 0)],
['next scan card', scanCompletionSummary.next_title || 'n/a'],
['next scan target', scanCompletionSummary.next_target_section || 'n/a'],
['next scan hint', scanCompletionSummary.next_hint || 'n/a'],
])
);
}
if (scanHandoffSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['scan handoff', scanHandoffSummary.status || 'idle'],
['handoff markers', String(scanHandoffSummary.marker_count ?? 0)],
['next handoff marker', scanHandoffSummary.next_marker || 'n/a'],
['next handoff target', scanHandoffSummary.next_target_section || 'n/a'],
['next handoff prompt', scanHandoffSummary.next_prompt || 'n/a'],
['handoff stale policy', scanHandoffSummary.handoff_stale_policy || 'n/a'],
['handoff stale warnings', String(scanHandoffSummary.stale_warning_count ?? 0)],
['handoff cleanup candidates', String(scanHandoffSummary.cleanup_candidate_count ?? 0)],
['handoff overdue cleanup', String(scanHandoffSummary.overdue_cleanup_count ?? 0)],
['handoff next cleanup', scanHandoffSummary.next_cleanup_title || scanHandoffSummary.next_cleanup_marker || 'n/a'],
['handoff cleanup prompt', scanHandoffSummary.next_cleanup_prompt || 'n/a'],
['handoff lane groups', formatList((scanHandoffSummary.handoff_lane_groups || []).map((item) => `${item.label || item.status}: ${item.count ?? 0}`))],
['handoff lane overdue', formatList((scanHandoffSummary.handoff_lane_groups || []).filter((item) => Number(item.overdue_count || 0) > 0).map((item) => `${item.label || item.status}: ${item.overdue_count}`))],
['handoff lifecycle', formatJsonInline(scanHandoffSummary.handoff_lifecycle_summary?.state_counts || {})],
['resume queue', String(scanHandoffSummary.resume_queue_count ?? 0)],
['resume queue items', formatList((scanHandoffSummary.operator_resume_queue || []).map((item) => `${item.resume_action_label || 'Resume'}: ${item.title || item.target_section}`))],
['resume persistence', scanHandoffSummary.resume_queue_persistence_status || 'n/a'],
['resume persistence key', scanHandoffSummary.resume_queue_persistence_key || 'n/a'],
['resolved lane states', formatJsonInline(scanHandoffSummary.resolved_lane_state_counts || {})],
['resolved lanes', String(scanHandoffSummary.resolved_lane_count ?? 0)],
['unresolved lanes', String(scanHandoffSummary.unresolved_lane_count ?? 0)],
['next resolved lane prompt', scanHandoffSummary.next_resolved_lane_prompt || 'n/a'],
['resume history', String(scanHandoffSummary.resume_history_count ?? 0)],
['resume latest event', scanHandoffSummary.resume_history_latest_event || 'n/a'],
['stale persistence cleanup', String(scanHandoffSummary.stale_persistence_cleanup_count ?? 0)],
['next persistence cleanup', scanHandoffSummary.next_stale_persistence_cleanup_key || 'n/a'],
['persistence cleanup prompt', scanHandoffSummary.next_stale_persistence_cleanup_prompt || 'n/a'],
['resume backlog groups', formatList((scanHandoffSummary.resume_backlog_groups || []).map((item) => `${item.label || item.resume_backlog_group}: ${item.count ?? 0}`))],
['grouped resume summary', formatList((scanHandoffSummary.grouped_resume_handoff_summary || []).map((item) => item.summary || `${item.label}: ${item.count ?? 0}`))],
['cleanup action ready', String(scanHandoffSummary.cleanup_action_ready_count ?? 0)],
['next cleanup action', scanHandoffSummary.next_cleanup_action_label || 'n/a'],
['next cleanup action prompt', scanHandoffSummary.next_cleanup_action_prompt || 'n/a'],
['cleanup execution log', String(scanHandoffSummary.cleanup_execution_log_count ?? 0)],
['cleanup execution events', formatList((scanHandoffSummary.cleanup_execution_log || []).map((item) => `${item.event}: ${item.status}`))],
['next cleanup execution', scanHandoffSummary.next_cleanup_execution_prompt || 'n/a'],
['next resume action', scanHandoffSummary.next_resume_action_label || 'n/a'],
['next resume prompt', scanHandoffSummary.next_resume_prompt || 'n/a'],
['handoff cleanup recommendation', scanHandoffSummary.handoff_cleanup_recommendation || 'n/a'],
['default stale after', formatDurationSeconds(scanHandoffSummary.default_stale_after_seconds)],
['saved handoff marker', assistantScanHandoffMarker?.marker || 'n/a'],
['saved handoff title', assistantScanHandoffMarker?.title || 'n/a'],
['saved handoff time', formatTimestamp(assistantScanHandoffMarker?.saved_ts)],
['saved handoff age', savedHandoffAge.age_label],
['saved handoff status', savedHandoffAge.status],
['saved handoff snoozed until', savedHandoffAge.snooze_label],
['saved handoff snooze reason', assistantScanHandoffMarker?.snooze_reason || 'n/a'],
['saved handoff warning', savedHandoffAge.warning],
])
);
const handoffActions = [];
if (scanHandoffSummary.next_marker) {
const nextHandoff = (scanHandoffSummary.handoff_markers || []).find((item) => item.handoff_marker === scanHandoffSummary.next_marker) || {};
handoffActions.push({
label: 'Persist Next Handoff',
onClick: () => {
persistAssistantScanHandoffMarker({
marker: scanHandoffSummary.next_marker,
title: nextHandoff.title || scanHandoffSummary.next_target_section || 'Scan',
target_section: scanHandoffSummary.next_target_section || '',
status: 'next_handoff',
stale_after_seconds: nextHandoff.stale_after_seconds || scanHandoffSummary.default_stale_after_seconds || 3600,
stale_warning: nextHandoff.stale_warning || '',
snooze_seconds: nextHandoff.snooze_seconds || 1800,
saved_ts: new Date().toISOString(),
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
});
}
if (assistantScanHandoffMarker?.target_section) {
handoffActions.push({
label: 'Open Saved Handoff',
onClick: () => revealAssistantSection(assistantScanHandoffMarker.target_section),
});
}
if (assistantScanHandoffMarker) {
(scanHandoffSummary.snooze_options || []).forEach((option) => {
handoffActions.push({
label: option.label || 'Snooze',
onClick: () => {
snoozeAssistantScanHandoffMarker(option.seconds || assistantScanHandoffMarker.snooze_seconds || 1800, 'operator_snooze');
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
});
});
if (assistantScanHandoffMarker.snoozed_until) {
handoffActions.push({
label: 'Clear Snooze',
onClick: () => {
const nextMarker = { ...assistantScanHandoffMarker };
delete nextMarker.snoozed_until;
delete nextMarker.snooze_reason;
persistAssistantScanHandoffMarker(nextMarker);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
});
}
handoffActions.push({
label: 'Clear Handoff',
onClick: () => {
persistAssistantScanHandoffMarker(null);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
});
}
if (handoffActions.length) {
decisionAssistantPanel.appendChild(buildActionBar(handoffActions));
}
}
}
if (focusWorkspaceContext) {
appendSectionTitle(decisionAssistantPanel, 'Focus Workspace');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['focus status', focusWorkspaceContext.status || 'idle'],
['focus title', resolvedFocusCandidate?.title || focusWorkspaceContext.focus_title || 'n/a'],
['focus session', resolvedFocusCandidate?.session_code || focusWorkspaceContext.focus_session_code || 'n/a'],
['focus tier', resolvedFocusCandidate?.tier || focusWorkspaceContext.focus_tier || 'n/a'],
['focus model', resolvedFocusCandidate?.model_code || focusWorkspaceContext.focus_model_code || 'n/a'],
['focus detail', resolvedFocusCandidate?.detail || focusWorkspaceContext.focus_detail || 'n/a'],
['focus persistence', focusWorkspaceContext.focus_persistence_status || 'n/a'],
['focus profile', focusWorkspaceContext.focus_profile_label || selectedProfileKey],
['history window', String(focusWorkspaceContext.focus_history_window_hours ?? 'n/a')],
['focus candidate notes', String(reviewEntrypoints?.focus_note_count ?? 0)],
['next focus prompt', focusWorkspaceContext.next_focus_prompt || 'n/a'],
])
);
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Persist Focus',
onClick: async () => {
if (!resolvedFocusCandidate?.candidate_id) return;
persistAssistantFocusCandidateId(resolvedFocusCandidate.candidate_id);
await persistAssistantFocusCandidateServer(resolvedFocusCandidate.candidate_id);
await refreshDashboard();
},
},
{
label: 'Clear Focus',
onClick: async () => {
persistAssistantFocusCandidateId('');
await persistAssistantFocusCandidateServer(null);
await refreshDashboard();
},
},
])
);
const focusGrid = createElement('div', 'cards assistant-workspace-rail-grid');
(focusWorkspaceContext.workspace_sections || []).forEach((item) => {
const card = buildItemCard(
item.section || 'section',
item.status || 'idle',
[
['prompt', item.prompt || 'n/a'],
['target', item.target_section || 'n/a'],
],
[{
label: `Open ${item.section || 'Section'}`,
onClick: () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.section || '')),
}]
);
card.classList.add('clickable-card');
card.addEventListener('click', () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.section || '')));
focusGrid.appendChild(card);
});
decisionAssistantPanel.appendChild(focusGrid);
}
if (assistantLoopQueue.length) {
appendSectionTitle(decisionAssistantPanel, 'Loop Queue');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['loop queue', assistantLoopSummary?.status || 'idle'],
['loop items', String(assistantLoopSummary?.queue_count ?? assistantLoopQueue.length)],
['loop lanes', formatJsonInline(assistantLoopSummary?.lane_counts || {})],
['next lane', assistantLoopSummary?.next_lane || 'n/a'],
['next action', assistantLoopSummary?.next_action_label || 'n/a'],
['next target', assistantLoopSummary?.next_target_section || 'n/a'],
['next prompt', assistantLoopSummary?.next_prompt || 'n/a'],
['queue hint', assistantLoopSummary?.queue_hint || 'n/a'],
])
);
const loopGrid = createElement('div', 'cards assistant-workspace-rail-grid');
assistantLoopQueue.forEach((item) => {
const card = buildItemCard(
item.title || item.queue_id || 'loop item',
item.status || 'active',
[
['lane', item.lane || 'workspace'],
['prompt', item.prompt || 'n/a'],
['target', item.target_section || 'n/a'],
['priority', String(item.priority_rank ?? 'n/a')],
],
[{
label: item.action_label || 'Open',
onClick: () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.title || 'loop')),
}]
);
card.classList.add('clickable-card');
card.addEventListener('click', () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.title || 'loop')));
loopGrid.appendChild(card);
});
decisionAssistantPanel.appendChild(loopGrid);
}
if (continuousWorkspaceRail.length) {
appendSectionTitle(decisionAssistantPanel, 'Workspace Rail');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['continuous workspace', continuousWorkspaceSummary?.status || summary.continuous_workspace_status || 'idle'],
['workspace rail items', String(continuousWorkspaceSummary?.rail_count ?? continuousWorkspaceRail.length)],
['workspace active/watch', `${continuousWorkspaceSummary?.active_count ?? 0} / ${continuousWorkspaceSummary?.watch_count ?? 0}`],
['workspace attention', String(continuousWorkspaceSummary?.attention_count ?? 0)],
['workspace next', continuousWorkspaceSummary?.next_section || 'n/a'],
['workspace next action', continuousWorkspaceSummary?.next_action || 'n/a'],
['workspace next prompt', continuousWorkspaceSummary?.next_handoff_prompt || 'n/a'],
['workspace path', continuousWorkspaceSummary?.rail_path || formatList(continuousWorkspaceRail.map((item) => item.section || 'section'))],
['continuity hint', continuousWorkspaceSummary?.continuity_hint || 'n/a'],
['workspace handoff', workspaceContinuityHandoff?.status || 'n/a'],
['ready sections', formatList(workspaceContinuityHandoff?.ready_sections || [])],
['watch sections', formatList(workspaceContinuityHandoff?.watch_sections || [])],
['loop sections', formatList(workspaceContinuityHandoff?.loop_sections || [])],
['next loop prompt', workspaceContinuityHandoff?.next_loop_prompt || 'n/a'],
])
);
const railGrid = createElement('div', 'cards assistant-workspace-rail-grid');
continuousWorkspaceRail.forEach((item) => {
const card = buildItemCard(
item.navigation_label || item.section || 'workspace',
item.status || 'idle',
[
['lane', item.lane_group || 'workspace'],
['attention', item.attention_level || 'low'],
['summary', item.summary || 'n/a'],
['next action', item.next_action || 'n/a'],
['handoff prompt', item.handoff_prompt || 'n/a'],
['completion hint', item.completion_hint || 'n/a'],
['target', item.target_section || 'n/a'],
],
[{
label: item.next_action || 'Open Section',
onClick: () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.section || '')),
}]
);
card.classList.add('clickable-card');
card.addEventListener('click', () => revealAssistantSection(item.target_section || normalizeAssistantSectionId(item.section || '')));
railGrid.appendChild(card);
});
decisionAssistantPanel.appendChild(railGrid);
}
if (liveAnalysisAssistantSummary) {
appendSectionTitle(decisionAssistantPanel, 'Read-only Live Analysis');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['read-only live analysis', liveAnalysisAssistantSummary.status || 'n/a'],
['ready_for_readonly_live_analysis', String(Boolean(liveAnalysisAssistantSummary.ready_for_readonly_live_analysis))],
['must_not_trade', String(Boolean(liveAnalysisAssistantSummary.must_not_trade))],
['No order submission', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.no_order_submission))],
['Not a buy/sell instruction', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.not_buy_sell_instruction))],
['Execution remains disabled', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.execution_remains_disabled))],
['health', readonlyLiveHealthSummary?.status || 'n/a'],
['runtime health', readonlyLiveHealthSummary?.runtime_health || 'n/a'],
['market freshness', readonlyLiveHealthSummary?.market_freshness || 'n/a'],
['broker/account context', readonlyLiveHealthSummary?.broker_account_context || 'n/a'],
['latest decision packet timestamp', formatTimestamp(readonlyLiveHealthSummary?.latest_decision_packet_timestamp)],
['latest review packet timestamp', formatTimestamp(readonlyLiveHealthSummary?.latest_review_packet_timestamp)],
['current candidate count', String(readonlyLiveHealthSummary?.current_candidate_count ?? 0)],
['current blocker', readonlyLiveHealthSummary?.current_blocker || 'none'],
['recommendation', readonlyLiveHealthSummary?.recommendation || 'n/a'],
['allowed actions', formatList(liveAnalysisAssistantSummary.allowed_actions || [])],
['blocked actions', formatList(liveAnalysisAssistantSummary.blocked_actions || [])],
])
);
}
decisionAssistantPanel.appendChild(
buildInfoGrid([
['focus mode', summary.focus_mode || 'monitor_and_wait'],
['headline', summary.headline || 'n/a'],
['market posture', summary.market_posture || 'n/a'],
['risk posture', summary.risk_posture || 'n/a'],
['attention reason', summary.attention_reason || 'n/a'],
['current session', summary.current_session || 'n/a'],
['changed since last', summary.changed_since_last?.summary || 'n/a'],
['decision', `${evidence.decision_status || 'unknown'} / ${evidence.decision_action || 'monitor'}`],
['trust / mode', `${evidence.trust_classification || 'unknown'} / ${evidence.operator_mode || 'unknown'}`],
['market truth', `${evidence.market_freshness || 'unknown'} | ${evidence.stream_status || 'unknown'} | ${evidence.data_gap_status || 'unknown'}`],
['launch mode', evidence.launch_mode || 'unknown'],
['live analysis assistant ready', String(Boolean(evidence.live_analysis_assistant_ready))],
['readonly live health', evidence.readonly_live_health_status || 'n/a'],
['readonly account context', evidence.readonly_account_context_status || 'n/a'],
['must_not_trade', String(Boolean(evidence.must_not_trade))],
['shadow paper validation', evidence.shadow_paper_status || shadowPaperValidationSummary?.status || 'n/a'],
['next shadow gate', evidence.next_shadow_paper_gate || shadowPaperValidationSummary?.next_validation_gate || 'n/a'],
['top opportunity', opportunities[0]?.title || 'n/a'],
['watchlist tiers', `review ${watchlistSummary.review_now_count ?? 0} | strong ${watchlistSummary.strong_watch_count ?? 0} | soft ${watchlistSummary.soft_watch_count ?? 0}`],
['next watchlist focus', watchlistSummary.focus_matrix?.next_focus?.title || 'n/a'],
['watchlist focus prompt', watchlistSummary.next_watchlist_focus_prompt || 'n/a'],
['section nav', assistantSections.map((item) => item.title).join(' | ') || 'n/a'],
['no-trade reasons', formatList(summary.no_trade_reasons || [])],
['next actions', formatList(summary.next_actions || [])],
])
);
if (decisionSupportBoundarySummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['operator boundary', decisionSupportBoundarySummary.label || 'n/a'],
['boundary summary', decisionSupportBoundarySummary.operator_summary || 'n/a'],
['current model boundary', decisionSupportBoundarySummary.current_model_boundary || 'n/a'],
['live execution boundary', decisionSupportBoundarySummary.live_execution_boundary || 'n/a'],
['allowed operator actions', formatList(decisionSupportBoundarySummary.allowed_operator_actions || [])],
['blocked operator actions', formatList(decisionSupportBoundarySummary.blocked_operator_actions || [])],
['boundary next gate', decisionSupportBoundarySummary.next_boundary_gate || 'n/a'],
['boundary gate reason', decisionSupportBoundarySummary.next_boundary_gate_reason || 'n/a'],
])
);
}
if (decisionSupportPromotionSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['decision support promotion', decisionSupportPromotionSummary.status || 'n/a'],
['strict decision support ready', String(Boolean(decisionSupportPromotionSummary.strict_decision_support_ready))],
['current decision support ready', String(Boolean(decisionSupportPromotionSummary.current_decision_support_ready))],
['promotion model', decisionSupportPromotionSummary.candidate_model_code || 'n/a'],
['promotion classification', decisionSupportPromotionSummary.candidate_classification || 'n/a'],
['operator feedback samples', String(decisionSupportPromotionSummary.operator_review_sample_count ?? 0)],
['promotion criteria', `${decisionSupportPromotionSummary.passed_criteria_count ?? 0}/${decisionSupportPromotionSummary.required_criteria_count ?? 0}`],
['next promotion gate', decisionSupportPromotionSummary.next_promotion_gate || 'n/a'],
['promotion summary', decisionSupportPromotionSummary.operator_summary || 'n/a'],
])
);
}
if (shadowPaperValidationSummary) {
decisionAssistantPanel.appendChild(
buildActionBar([
{ label: 'Record Shadow Observation', onClick: () => recordShadowPaperObservation('pending') },
{ label: 'Agree Shadow Observation', onClick: () => recordShadowPaperObservation('agree') },
{ label: 'Disagree Shadow Observation', onClick: () => recordShadowPaperObservation('disagree') },
])
);
decisionAssistantPanel.appendChild(
buildInfoGrid([
['shadow paper validation', shadowPaperValidationSummary.status || 'n/a'],
['shadow validation status', shadowPaperValidationSummary.status || 'n/a'],
['shadow observed days', `${shadowPaperValidationSummary.observed_shadow_day_count ?? 0}/${shadowPaperValidationSummary.window_days ?? 0}`],
['shadow observation samples', String(shadowPaperValidationSummary.shadow_observation_count ?? 0)],
['shadow observation days', String(shadowPaperValidationSummary.shadow_observation_day_count ?? 0)],
['shadow candidates', String(shadowPaperValidationSummary.candidate_count ?? 0)],
['paper ticket samples', String(shadowPaperValidationSummary.paper_ticket_count ?? 0)],
['paper execution samples', String(shadowPaperValidationSummary.paper_execution_count ?? 0)],
['operator feedback samples', String(shadowPaperValidationSummary.operator_feedback_count ?? 0)],
['operator observation feedback', String(shadowPaperValidationSummary.operator_observation_feedback_count ?? 0)],
['journal samples', String(shadowPaperValidationSummary.journal_entry_count ?? 0)],
['risk violations', String(shadowPaperValidationSummary.risk_violation_count ?? 0)],
['shadow criteria', `${shadowPaperValidationSummary.passed_criteria_count ?? 0}/${shadowPaperValidationSummary.required_criteria_count ?? 0}`],
['next shadow gate', shadowPaperValidationSummary.next_validation_gate || 'n/a'],
['sample collection next actions', formatList(shadowPaperValidationSummary.sample_collection_plan?.next_actions || [])],
['real live after shadow', shadowPaperValidationSummary.execution_boundary || 'real_live_still_blocked'],
['shadow validation summary', shadowPaperValidationSummary.operator_summary || 'n/a'],
['shadow daily coverage', formatList((shadowPaperValidationSummary.daily_coverage || []).slice(-5).map((item) => `${item.date}: o${item.shadow_observation_count}/c${item.candidate_count}/p${item.paper_execution_count}/f${item.operator_feedback_count}`))],
])
);
}
if (assistantSections.length) {
decisionAssistantPanel.appendChild(
buildActionBar(
assistantSections.map((item) => ({
label: item.title,
onClick: () => revealAssistantSection(normalizeAssistantSectionId(item.title)),
}))
)
);
}
if (digestPreferenceProfile) {
appendSectionTitle(decisionAssistantPanel, 'Preferences');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['selected profile', selectedProfileKey],
['profile label', assistantPreferenceDraft?.profile_label || digestPreferenceProfile.profile_label || 'n/a'],
['draft status', assistantPreferenceDraftDirty ? 'unsaved_changes' : 'synced'],
['digest mode', assistantPreferenceDraft?.digest_mode || 'all_reminders'],
['preferred history kind', assistantPreferenceDraft?.preferred_history_kind || 'all'],
['importance threshold', String(assistantPreferenceDraft?.importance_threshold ?? 70)],
['history window hours', String(assistantPreferenceDraft?.history_window_hours ?? 24)],
['focus candidate', String(assistantPreferenceDraft?.focus_candidate_id ?? 'n/a')],
])
);
if (digestPreferenceProfile.available_profiles?.length) {
decisionAssistantPanel.appendChild(
buildActionBar(
digestPreferenceProfile.available_profiles.map((profile) => ({
label: profile.profile_key === selectedProfileKey
? `${profile.profile_label || profile.profile_key}`
: (profile.profile_label || profile.profile_key),
onClick: async () => {
if (assistantPreferenceDraftDirty && !window.confirm('Switch profile and discard unsaved changes?')) return;
persistAssistantDigestProfileKey(profile.profile_key || 'local_operator');
assistantPreferenceDraft = null;
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
}))
)
);
}
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'New Profile',
onClick: async () => {
const profileKey = window.prompt('New profile key', '');
if (!profileKey) return;
const profileLabel = window.prompt('New profile label', assistantPreferenceDraft?.profile_label || profileKey);
const created = await createAssistantPreferenceProfile({
profileKey,
profileLabel,
sourceProfileKey: null,
draft: assistantPreferenceDraft,
}).catch((error) => ({ status: 'error', reason: String(error) }));
if (created?.status !== 'created') {
showErrorPanel(created?.reason || created?.status || 'profile_create_failed');
return;
}
persistAssistantDigestProfileKey(created.profile_key || profileKey);
assistantPreferenceDraft = null;
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
},
{
label: 'Duplicate',
onClick: async () => {
const profileKey = window.prompt('Duplicate to profile key', `${selectedProfileKey}_copy`);
if (!profileKey) return;
const profileLabel = window.prompt('Duplicate profile label', `${assistantPreferenceDraft?.profile_label || selectedProfileKey} Copy`);
const created = await createAssistantPreferenceProfile({
profileKey,
profileLabel,
sourceProfileKey: selectedProfileKey,
draft: assistantPreferenceDraft,
}).catch((error) => ({ status: 'error', reason: String(error) }));
if (created?.status !== 'created') {
showErrorPanel(created?.reason || created?.status || 'profile_duplicate_failed');
return;
}
persistAssistantDigestProfileKey(created.profile_key || profileKey);
assistantPreferenceDraft = null;
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
},
{
label: 'Rename Label',
onClick: async () => {
const nextLabel = window.prompt('Profile label', assistantPreferenceDraft?.profile_label || selectedProfileKey);
if (!nextLabel) return;
const renamed = await renameAssistantPreferenceProfile({
profileKey: selectedProfileKey,
profileLabel: nextLabel,
}).catch((error) => ({ status: 'error', reason: String(error) }));
if (renamed?.status !== 'renamed') {
showErrorPanel(renamed?.reason || renamed?.status || 'profile_rename_failed');
return;
}
assistantPreferenceDraft = null;
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
},
{
label: 'Delete Profile',
onClick: async () => {
if (selectedProfileKey === 'local_operator') {
showErrorPanel('default_profile_protected');
return;
}
if (!window.confirm(`Delete profile ${selectedProfileKey}?`)) return;
const removed = await deleteAssistantPreferenceProfile(selectedProfileKey).catch((error) => ({ status: 'error', reason: String(error) }));
if (removed?.status !== 'deleted') {
showErrorPanel(removed?.reason || removed?.status || 'profile_delete_failed');
return;
}
persistAssistantDigestProfileKey('local_operator');
assistantPreferenceDraft = null;
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
},
])
);
const preferencePanel = createElement('div', 'assistant-preference-panel');
const fieldGrid = createElement('div', 'assistant-preference-fields');
const labelField = createElement('label', 'assistant-preference-field');
labelField.appendChild(createElement('span', 'metric', 'Profile Label'));
const labelInput = createElement('input', 'assistant-preference-input');
labelInput.type = 'text';
labelInput.value = assistantPreferenceDraft?.profile_label || '';
labelInput.addEventListener('input', (event) => {
updateAssistantPreferenceDraft({ profile_label: event.target.value });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
labelField.appendChild(labelInput);
fieldGrid.appendChild(labelField);
const modeField = createElement('label', 'assistant-preference-field');
modeField.appendChild(createElement('span', 'metric', 'Digest Mode'));
const modeSelect = createElement('select', 'assistant-preference-input');
(digestPreferenceProfile.available_modes || []).forEach((mode) => {
const option = createElement('option', '', mode);
option.value = mode;
option.selected = mode === (assistantPreferenceDraft?.digest_mode || 'all_reminders');
modeSelect.appendChild(option);
});
modeSelect.addEventListener('change', (event) => {
updateAssistantPreferenceDraft({ digest_mode: event.target.value || 'all_reminders' });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
modeField.appendChild(modeSelect);
fieldGrid.appendChild(modeField);
const kindField = createElement('label', 'assistant-preference-field');
kindField.appendChild(createElement('span', 'metric', 'Preferred History Kind'));
const kindSelect = createElement('select', 'assistant-preference-input');
[{ kind: 'all', label: 'all' }, ...(digestHistoryGroups || []).map((item) => ({ kind: item.kind, label: item.kind }))].forEach((item) => {
const option = createElement('option', '', item.label || item.kind);
option.value = item.kind || 'all';
option.selected = (item.kind || 'all') === (assistantPreferenceDraft?.preferred_history_kind || 'all');
kindSelect.appendChild(option);
});
kindSelect.addEventListener('change', (event) => {
updateAssistantPreferenceDraft({ preferred_history_kind: event.target.value || 'all' });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
kindField.appendChild(kindSelect);
fieldGrid.appendChild(kindField);
const thresholdField = createElement('label', 'assistant-preference-field');
thresholdField.appendChild(createElement('span', 'metric', 'Importance Threshold'));
const thresholdInput = createElement('input', 'assistant-preference-input');
thresholdInput.type = 'number';
thresholdInput.min = '0';
thresholdInput.max = '100';
thresholdInput.value = String(assistantPreferenceDraft?.importance_threshold ?? 70);
thresholdInput.addEventListener('input', (event) => {
updateAssistantPreferenceDraft({ importance_threshold: Number(event.target.value || 70) });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
thresholdField.appendChild(thresholdInput);
fieldGrid.appendChild(thresholdField);
const historyWindowField = createElement('label', 'assistant-preference-field');
historyWindowField.appendChild(createElement('span', 'metric', 'History Window Hours'));
const historyWindowInput = createElement('input', 'assistant-preference-input');
historyWindowInput.type = 'number';
historyWindowInput.min = '1';
historyWindowInput.max = '240';
historyWindowInput.value = String(assistantPreferenceDraft?.history_window_hours ?? 24);
historyWindowInput.addEventListener('input', (event) => {
updateAssistantPreferenceDraft({ history_window_hours: Number(event.target.value || 24) });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
historyWindowField.appendChild(historyWindowInput);
fieldGrid.appendChild(historyWindowField);
preferencePanel.appendChild(fieldGrid);
if (digestPreferenceProfile.importance_templates?.length) {
const templateGrid = createElement('div', 'assistant-preference-template-grid');
(digestPreferenceProfile.importance_templates || []).forEach((item) => {
const templateField = createElement('label', 'assistant-preference-field');
templateField.appendChild(createElement('span', 'metric', item.template || 'template'));
const templateInput = createElement('input', 'assistant-preference-input');
templateInput.type = 'number';
templateInput.min = '0';
templateInput.max = '100';
templateInput.value = String(assistantPreferenceDraft?.importance_templates?.[item.template] ?? item.threshold ?? item.default_threshold ?? 0);
templateInput.addEventListener('input', (event) => {
updateAssistantPreferenceTemplateDraft(item.template, Number(event.target.value || 0));
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
});
templateField.appendChild(templateInput);
templateField.appendChild(createElement('div', 'metric', item.description || ''));
templateGrid.appendChild(templateField);
});
preferencePanel.appendChild(templateGrid);
}
preferencePanel.appendChild(
buildActionBar([
{
label: 'Save Preferences',
onClick: async () => {
const saved = await persistAssistantDigestPreferenceServer({
profileKey: selectedProfileKey,
digestMode: assistantPreferenceDraft?.digest_mode || 'all_reminders',
preferredHistoryKind: assistantPreferenceDraft?.preferred_history_kind === 'all' ? null : (assistantPreferenceDraft?.preferred_history_kind || null),
importanceThreshold: assistantPreferenceDraft?.importance_threshold || 70,
payload: {
profile_label: assistantPreferenceDraft?.profile_label || selectedProfileKey,
history_window_hours: assistantPreferenceDraft?.history_window_hours || 24,
importance_templates: { ...((assistantPreferenceDraft && assistantPreferenceDraft.importance_templates) || {}) },
archive_defaults: { ...((assistantPreferenceDraft && assistantPreferenceDraft.archive_defaults) || {}) },
},
});
if (!saved) {
showErrorPanel('preference_save_failed');
return;
}
persistAssistantDigestPreferenceMode(assistantPreferenceDraft?.digest_mode || 'all_reminders');
persistAssistantHistoryKindFilter(assistantPreferenceDraft?.preferred_history_kind || 'all');
assistantPreferenceDraftDirty = false;
await refreshDashboard();
},
},
{
label: 'Revert Draft',
onClick: () => {
resetAssistantPreferenceDraftToServer(summary);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Reset Defaults',
onClick: () => {
resetAssistantPreferenceDraftToDefaults(summary);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
])
);
if (assistantPreferenceDraftDirty) {
preferencePanel.appendChild(createElement('div', 'assistant-preference-dirty', 'Unsaved preference changes are staged locally. Save or revert before switching workflow.'));
}
decisionAssistantPanel.appendChild(preferencePanel);
}
if (digestSurface) {
appendSectionTitle(decisionAssistantPanel, 'Digest');
if (archiveOperatorOverview) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['archive operator overview', archiveOperatorOverview.status || 'idle'],
['digest trend status', archiveOperatorOverview.digest_trend_status || 'n/a'],
['workflow trend status', archiveOperatorOverview.workflow_trend_status || 'n/a'],
['digest snapshots', String(archiveOperatorOverview.digest_snapshot_count ?? 0)],
['workflow snapshots', String(archiveOperatorOverview.workflow_snapshot_count ?? 0)],
['digest baseline status', archiveOperatorOverview.digest_baseline_status || 'n/a'],
['workflow baseline status', archiveOperatorOverview.workflow_baseline_status || 'n/a'],
['digest baseline delta', archiveOperatorOverview.digest_baseline_delta_status || 'n/a'],
['workflow baseline delta', archiveOperatorOverview.workflow_baseline_delta_status || 'n/a'],
['digest baseline delta story', archiveOperatorOverview.digest_baseline_delta_story || 'n/a'],
['workflow baseline delta story', archiveOperatorOverview.workflow_baseline_delta_story || 'n/a'],
['overview story', archiveOperatorOverview.operator_overview_story || 'n/a'],
['overview prompt', archiveOperatorOverview.next_overview_prompt || 'n/a'],
])
);
}
decisionAssistantPanel.appendChild(
buildInfoGrid([
['digest status', digestSurface.status || 'idle'],
['digest summary', digestSurface.summary || 'n/a'],
['reminders', String(digestSurface.reminder_count ?? 0)],
['high priority reminders', String(digestSurface.high_priority_count ?? 0)],
['high value reminders', String(digestSurface.high_value_reminder_count ?? 0)],
['digest preference', effectiveDigestPreferenceMode || 'all_reminders'],
['selected profile', selectedProfileKey],
['profile label', digestPreferenceProfile?.profile_label || 'n/a'],
['preference default', digestPreferenceProfile?.default_mode || 'n/a'],
['preference persistence', digestPreferenceProfile?.persistence_status || 'n/a'],
['preference threshold', String(digestPreferenceProfile?.importance_threshold ?? 'n/a')],
['preference updated', formatTimestamp(digestPreferenceProfile?.persisted_updated_ts)],
['history window hours', String(digestPreferenceProfile?.history_window_hours ?? 'n/a')],
['preferred history kind', digestPreferenceProfile?.preferred_history_kind || 'n/a'],
['preferred template', digestPreferenceProfile?.preferred_importance_template || 'n/a'],
['preference reason', digestPreferenceProfile?.profile_reason || 'n/a'],
['focus candidate', String(digestPreferenceProfile?.focus_candidate_id ?? digestSurface.focus_candidate_id ?? 'n/a')],
['focus-related reminders', String(digestSurface.focus_related_reminder_count ?? 0)],
['next focus reminder', digestSurface.next_focus_related_reminder?.title || 'n/a'],
['visible reminders', String(reminderCards.length)],
['important change filter', `${digestSurface.important_change_filter?.mode || 'n/a'} / ${digestSurface.important_change_filter?.threshold ?? 'n/a'}`],
['importance templates', formatJsonInline(digestSurface.important_change_filter?.template_counts || {})],
['next high value change', digestSurface.next_high_value_change?.title || 'n/a'],
['review-back actions', String(digestSurface.digest_review_back_action_count ?? 0)],
['next review-back', digestSurface.next_digest_review_back_action?.label || 'n/a'],
['review-back prompts', formatList((digestSurface.digest_review_back_actions || []).map((item) => item.prompt || item.label))],
['history browser', digestHistoryBrowser?.status || 'idle'],
['history browser options', String(digestHistoryBrowser?.option_count ?? 0)],
['next browser filter', digestHistoryBrowser?.next_filter_label || 'n/a'],
['next browser prompt', digestHistoryBrowser?.next_filter_prompt || 'n/a'],
['digest action queue', String(digestSurface.digest_action_queue_count ?? 0)],
['next digest action', digestSurface.next_digest_action?.label || 'n/a'],
['next digest prompt', digestSurface.next_digest_action?.prompt || 'n/a'],
['digest archive', String(digestSurface.digest_history_archive_count ?? 0)],
['next archive review', digestSurface.next_digest_history_archive_review || 'n/a'],
['archive compare', digestArchiveCompare?.status || 'idle'],
['archive compare summary', digestArchiveCompare?.summary || 'n/a'],
['digest persistence', digestSurface.digest_persistence_status || 'n/a'],
['digest history', String(digestSurface.history_count ?? 0)],
['digest kinds', formatList(digestSurface.history_summary?.kinds || [])],
['recommended history kind', digestSurface.history_summary?.recommended_kind || 'n/a'],
['recommended history count', String(digestSurface.history_summary?.recommended_count ?? 0)],
['fresh history groups', String(digestSurface.history_summary?.fresh_kind_count ?? 0)],
['stale history groups', String(digestSurface.history_summary?.stale_kind_count ?? 0)],
['refresh-needed groups', String(digestSurface.history_summary?.refresh_needed_count ?? 0)],
['refresh confirmations', String(digestSurface.history_summary?.refresh_confirmation_count ?? 0)],
['refresh confirmation needed', String(digestSurface.history_summary?.refresh_confirmation_needed_count ?? 0)],
['freshness proofs', String(digestSurface.history_summary?.freshness_proof_count ?? 0)],
['freshness proof gaps', String(digestSurface.history_summary?.freshness_proof_gap_count ?? 0)],
['proof aging trend', formatJsonInline(digestSurface.history_summary?.proof_aging_trend_counts || {})],
['stale proof escalations', String(digestSurface.history_summary?.stale_proof_escalation_count ?? 0)],
['next stale proof kind', digestSurface.history_summary?.next_stale_proof_kind || 'n/a'],
['next stale proof prompt', digestSurface.history_summary?.next_stale_proof_prompt || 'n/a'],
['proof follow-up queue', String(digestSurface.history_summary?.proof_follow_up_queue_count ?? 0)],
['stale proof follow-ups', String(digestSurface.history_summary?.stale_proof_follow_up_count ?? 0)],
['proof follow-up age', formatJsonInline(digestSurface.history_summary?.proof_follow_up_age_counts || {})],
['oldest proof follow-up', digestSurface.history_summary?.oldest_proof_follow_up_kind || 'n/a'],
['oldest proof age', formatDurationSeconds(digestSurface.history_summary?.oldest_proof_follow_up_age_seconds)],
['resolved proofs', String(digestSurface.history_summary?.resolved_proof_count ?? 0)],
['proof resolution states', formatJsonInline(digestSurface.history_summary?.proof_resolution_state_counts || {})],
['proof resolution history', formatList((digestSurface.history_summary?.proof_resolution_history || []).map((item) => `${item.kind}:${item.state}`))],
['proof SLA states', formatJsonInline(digestSurface.history_summary?.proof_resolution_sla_status_counts || {})],
['proof SLA breaches', String(digestSurface.history_summary?.proof_resolution_sla_breach_count ?? 0)],
['proof SLA queue', String(digestSurface.history_summary?.proof_resolution_sla_queue_count ?? 0)],
['stale proof suppressions', String(digestSurface.history_summary?.repeated_stale_proof_suppression_count ?? 0)],
['next proof SLA kind', digestSurface.history_summary?.next_proof_resolution_sla_kind || 'n/a'],
['next proof SLA prompt', digestSurface.history_summary?.next_proof_resolution_sla_prompt || 'n/a'],
['proof SLA backlog', String(digestSurface.history_summary?.proof_sla_backlog_count ?? 0)],
['proof SLA routes', formatJsonInline(digestSurface.history_summary?.proof_sla_backlog_routes || {})],
['freshness debt', digestSurface.history_summary?.freshness_debt_summary?.status || 'n/a'],
['freshness debt score', String(digestSurface.history_summary?.freshness_debt_summary?.debt_score_total ?? 0)],
['next freshness debt', digestSurface.history_summary?.next_freshness_debt_prompt || 'n/a'],
['freshness debt trends', formatJsonInline(digestSurface.history_summary?.freshness_debt_trend_counts || {})],
['SLA recovery recs', String(digestSurface.history_summary?.sla_recovery_recommendation_count ?? 0)],
['next SLA recovery', digestSurface.history_summary?.next_sla_recovery_recommendation?.label || 'n/a'],
['next SLA recovery prompt', digestSurface.history_summary?.next_sla_recovery_prompt || 'n/a'],
['next proof follow-up', digestSurface.history_summary?.next_proof_follow_up_prompt || 'n/a'],
['confirmation trail items', String(digestSurface.history_summary?.refresh_confirmation_trail_count ?? 0)],
['confirmation trail', formatList((digestSurface.history_summary?.refresh_confirmation_trail || []).map((item) => `${item.kind}:${item.proof_label}`))],
['refresh evidence anchors', String(digestSurface.history_summary?.refresh_evidence_anchor_count ?? 0)],
['refresh prompts', formatList((digestSurface.history_summary?.refresh_prompts || []).map((item) => `${item.kind}: ${item.prompt}`))],
['history filter', activeHistoryFilter || 'all'],
['digest latest', formatTimestamp(digestSurface.history_summary?.latest_ts)],
['digest top opportunity', digestSurface.top_opportunity_title || 'n/a'],
['learning status', digestSurface.learning_status || 'n/a'],
])
);
}
if (digestSurface?.digest_action_queue?.length) {
const digestActionGrid = createElement('div', 'cards assistant-tight-grid');
(digestSurface.digest_action_queue || []).forEach((item) => {
digestActionGrid.appendChild(
buildItemCard(
item.label || 'digest action',
item.priority || item.source || 'n/a',
[
['source', item.source || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(digestActionGrid);
}
if (digestHistoryBrowser?.filter_options?.length) {
const browserBar = buildActionBar(
digestHistoryBrowser.filter_options.map((item) => ({
label: `${item.label || item.kind}${item.recommended ? ' *' : ''}`,
onClick: () => {
persistAssistantHistoryKindFilter(item.kind || 'all');
updateAssistantPreferenceDraft({ preferred_history_kind: item.kind || 'all' });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}))
);
decisionAssistantPanel.appendChild(browserBar);
}
const digestArchivePanel = createElement('div', 'assistant-archive-panel');
const digestArchiveControls = createElement('div', 'assistant-archive-controls');
const digestArchiveProfileField = createElement('label', 'assistant-preference-field');
digestArchiveProfileField.appendChild(createElement('span', 'metric', 'Archive Profile'));
const digestArchiveProfileInput = createElement('input', 'assistant-preference-input');
digestArchiveProfileInput.type = 'text';
digestArchiveProfileInput.value = assistantDigestArchiveState.profile_key || selectedProfileKey;
digestArchiveProfileField.appendChild(digestArchiveProfileInput);
digestArchiveControls.appendChild(digestArchiveProfileField);
const digestArchiveScopeField = createElement('label', 'assistant-preference-field');
digestArchiveScopeField.appendChild(createElement('span', 'metric', 'Profile Scope'));
const digestArchiveScopeSelect = createElement('select', 'assistant-preference-input');
['selected_profile', 'all_profiles'].forEach((scope) => {
const option = createElement('option', '', scope);
option.value = scope;
option.selected = scope === (assistantDigestArchiveState.profile_scope || digestArchiveSavedDefaults.profile_scope || 'selected_profile');
digestArchiveScopeSelect.appendChild(option);
});
digestArchiveScopeField.appendChild(digestArchiveScopeSelect);
digestArchiveControls.appendChild(digestArchiveScopeField);
const digestArchivePresetField = createElement('label', 'assistant-preference-field');
digestArchivePresetField.appendChild(createElement('span', 'metric', 'Query Preset'));
const digestArchivePresetSelect = createElement('select', 'assistant-preference-input');
[{ preset_id: '', label: 'custom' }, ...((digestArchiveData?.available_query_presets || []))].forEach((preset) => {
const option = createElement('option', '', preset.label || preset.preset_id || 'custom');
option.value = preset.preset_id || '';
option.selected = (preset.preset_id || '') === (assistantDigestArchiveState.query_preset || digestArchiveSavedDefaults.query_preset || '');
digestArchivePresetSelect.appendChild(option);
});
digestArchivePresetField.appendChild(digestArchivePresetSelect);
digestArchiveControls.appendChild(digestArchivePresetField);
const digestArchiveModeField = createElement('label', 'assistant-preference-field');
digestArchiveModeField.appendChild(createElement('span', 'metric', 'Archive Mode'));
const digestArchiveModeSelect = createElement('select', 'assistant-preference-input');
[{ value: '', label: 'all' }, ...(digestPreferenceProfile?.available_modes || []).map((mode) => ({ value: mode, label: mode }))].forEach((item) => {
const option = createElement('option', '', item.label);
option.value = item.value;
option.selected = item.value === (assistantDigestArchiveState.digest_mode || '');
digestArchiveModeSelect.appendChild(option);
});
digestArchiveModeField.appendChild(digestArchiveModeSelect);
digestArchiveControls.appendChild(digestArchiveModeField);
const digestArchiveKindField = createElement('label', 'assistant-preference-field');
digestArchiveKindField.appendChild(createElement('span', 'metric', 'Archive Kind'));
const digestArchiveKindSelect = createElement('select', 'assistant-preference-input');
[{ value: '', label: 'all' }, ...(digestHistoryGroups || []).map((item) => ({ value: item.kind, label: item.kind }))].forEach((item) => {
const option = createElement('option', '', item.label);
option.value = item.value;
option.selected = item.value === (assistantDigestArchiveState.preferred_history_kind || '');
digestArchiveKindSelect.appendChild(option);
});
digestArchiveKindField.appendChild(digestArchiveKindSelect);
digestArchiveControls.appendChild(digestArchiveKindField);
const digestArchiveSearchField = createElement('label', 'assistant-preference-field');
digestArchiveSearchField.appendChild(createElement('span', 'metric', 'Search Text'));
const digestArchiveSearchInput = createElement('input', 'assistant-preference-input');
digestArchiveSearchInput.type = 'text';
digestArchiveSearchInput.value = assistantDigestArchiveState.query_text || '';
digestArchiveSearchInput.placeholder = 'summary, reminder, candidate...';
digestArchiveSearchField.appendChild(digestArchiveSearchInput);
digestArchiveControls.appendChild(digestArchiveSearchField);
const digestArchiveAfterField = createElement('label', 'assistant-preference-field');
digestArchiveAfterField.appendChild(createElement('span', 'metric', 'Created After'));
const digestArchiveAfterInput = createElement('input', 'assistant-preference-input');
digestArchiveAfterInput.type = 'datetime-local';
digestArchiveAfterInput.value = assistantDigestArchiveState.created_after || '';
digestArchiveAfterField.appendChild(digestArchiveAfterInput);
digestArchiveControls.appendChild(digestArchiveAfterField);
const digestArchiveBeforeField = createElement('label', 'assistant-preference-field');
digestArchiveBeforeField.appendChild(createElement('span', 'metric', 'Created Before'));
const digestArchiveBeforeInput = createElement('input', 'assistant-preference-input');
digestArchiveBeforeInput.type = 'datetime-local';
digestArchiveBeforeInput.value = assistantDigestArchiveState.created_before || '';
digestArchiveBeforeField.appendChild(digestArchiveBeforeInput);
digestArchiveControls.appendChild(digestArchiveBeforeField);
const digestArchiveLimitField = createElement('label', 'assistant-preference-field');
digestArchiveLimitField.appendChild(createElement('span', 'metric', 'Archive Limit'));
const digestArchiveLimitInput = createElement('input', 'assistant-preference-input');
digestArchiveLimitInput.type = 'number';
digestArchiveLimitInput.min = '1';
digestArchiveLimitInput.max = '50';
digestArchiveLimitInput.value = String(assistantDigestArchiveState.limit || 12);
digestArchiveLimitField.appendChild(digestArchiveLimitInput);
digestArchiveControls.appendChild(digestArchiveLimitField);
digestArchivePanel.appendChild(digestArchiveControls);
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Apply Archive Filters',
onClick: async () => {
await fetchAssistantDigestArchive({
profile_key: digestArchiveProfileInput.value || selectedProfileKey,
profile_scope: digestArchiveScopeSelect.value || 'selected_profile',
query_preset: digestArchivePresetSelect.value || '',
digest_mode: digestArchiveModeSelect.value || '',
preferred_history_kind: digestArchiveKindSelect.value || '',
query_text: digestArchiveSearchInput.value || '',
created_after: digestArchiveAfterInput.value || '',
created_before: digestArchiveBeforeInput.value || '',
limit: Number(digestArchiveLimitInput.value || 12),
selected_left_id: assistantDigestArchiveState.selected_left_id,
selected_right_id: assistantDigestArchiveState.selected_right_id,
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Load More Archive',
onClick: async () => {
await fetchAssistantDigestArchive({
append: true,
profile_key: assistantDigestArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantDigestArchiveState.profile_scope || 'selected_profile',
query_preset: assistantDigestArchiveState.query_preset || '',
digest_mode: assistantDigestArchiveState.digest_mode || '',
preferred_history_kind: assistantDigestArchiveState.preferred_history_kind || '',
query_text: assistantDigestArchiveState.query_text || '',
created_after: assistantDigestArchiveState.created_after || '',
created_before: assistantDigestArchiveState.created_before || '',
limit: Number(assistantDigestArchiveState.limit || 12),
selected_left_id: assistantDigestArchiveState.selected_left_id,
selected_right_id: assistantDigestArchiveState.selected_right_id,
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Compare Selected Digests',
onClick: async () => {
if (!assistantDigestArchiveState.selected_left_id || !assistantDigestArchiveState.selected_right_id) {
showErrorPanel('select_two_digest_snapshots');
return;
}
await fetchAssistantDigestArchive({
profile_key: assistantDigestArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantDigestArchiveState.profile_scope || 'selected_profile',
query_preset: assistantDigestArchiveState.query_preset || '',
digest_mode: assistantDigestArchiveState.digest_mode || '',
preferred_history_kind: assistantDigestArchiveState.preferred_history_kind || '',
query_text: assistantDigestArchiveState.query_text || '',
created_after: assistantDigestArchiveState.created_after || '',
created_before: assistantDigestArchiveState.created_before || '',
limit: Number(assistantDigestArchiveState.limit || 12),
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Export Archive Results',
onClick: async () => {
const exportLimit = Math.max(Number(assistantDigestArchiveState.limit || 12), Number(digestArchiveData?.items?.length || 0));
const exportPayload = await fetchJson(`/trading/alerts/digest-history-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantDigestArchiveState.profile_scope || 'selected_profile',
query_preset: assistantDigestArchiveState.query_preset || '',
digest_mode: assistantDigestArchiveState.digest_mode || '',
preferred_history_kind: assistantDigestArchiveState.preferred_history_kind || '',
query_text: assistantDigestArchiveState.query_text || '',
created_after: assistantDigestArchiveState.created_after || '',
created_before: assistantDigestArchiveState.created_before || '',
limit: exportLimit,
offset: 0,
})}`);
assistantDigestArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || 'digest-archive-export.json', exportPayload);
},
},
{
label: 'Export Archive Compare',
onClick: async () => {
if (!assistantDigestArchiveState.selected_left_id || !assistantDigestArchiveState.selected_right_id) {
showErrorPanel('select_two_digest_snapshots');
return;
}
const exportLimit = Math.max(Number(assistantDigestArchiveState.limit || 12), Number(digestArchiveData?.items?.length || 0));
const exportPayload = await fetchJson(`/trading/alerts/digest-history-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantDigestArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantDigestArchiveState.profile_scope || 'selected_profile',
query_preset: assistantDigestArchiveState.query_preset || '',
digest_mode: assistantDigestArchiveState.digest_mode || '',
preferred_history_kind: assistantDigestArchiveState.preferred_history_kind || '',
query_text: assistantDigestArchiveState.query_text || '',
created_after: assistantDigestArchiveState.created_after || '',
created_before: assistantDigestArchiveState.created_before || '',
limit: exportLimit,
offset: 0,
left_id: assistantDigestArchiveState.selected_left_id,
right_id: assistantDigestArchiveState.selected_right_id,
})}`);
assistantDigestArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || 'digest-archive-compare-export.json', exportPayload);
},
},
{
label: 'Save Baseline',
onClick: async () => {
const baselineId = assistantDigestArchiveState.pinned_baseline_id || digestArchiveBaselineSummary?.baseline_snapshot_id;
if (!baselineId) {
showErrorPanel('digest_baseline_missing');
return;
}
await persistAssistantArchiveBaselinesServer({
profileKey: assistantDigestArchiveState.profile_key || selectedProfileKey,
digestSnapshotId: baselineId,
});
await refreshDashboard();
},
},
{
label: 'Save Digest Defaults',
onClick: async () => {
const saved = await persistAssistantDigestPreferenceServer({
profileKey: selectedProfileKey,
digestMode: assistantPreferenceDraft?.digest_mode || digestPreferenceProfile?.persisted_digest_mode || 'all_reminders',
preferredHistoryKind: assistantPreferenceDraft?.preferred_history_kind === 'all'
? null
: (assistantPreferenceDraft?.preferred_history_kind || digestPreferenceProfile?.preferred_history_kind || null),
importanceThreshold: assistantPreferenceDraft?.importance_threshold || digestPreferenceProfile?.importance_threshold || 70,
payload: {
profile_label: assistantPreferenceDraft?.profile_label || digestPreferenceProfile?.profile_label || selectedProfileKey,
history_window_hours: assistantPreferenceDraft?.history_window_hours || digestPreferenceProfile?.history_window_hours || 24,
importance_templates: { ...((assistantPreferenceDraft && assistantPreferenceDraft.importance_templates) || {}) },
archive_defaults: mergeAssistantArchiveDefaults(summary, {
digest: {
profile_scope: digestArchiveScopeSelect.value || 'selected_profile',
query_preset: digestArchivePresetSelect.value || '',
},
}),
},
});
if (!saved) {
showErrorPanel('digest_archive_defaults_save_failed');
return;
}
assistantPreferenceDraft = {
...(assistantPreferenceDraft || {}),
archive_defaults: mergeAssistantArchiveDefaults(summary, {
digest: {
profile_scope: digestArchiveScopeSelect.value || 'selected_profile',
query_preset: digestArchivePresetSelect.value || '',
},
}),
};
await refreshDashboard();
},
},
{
label: 'Use Saved Digest Defaults',
onClick: () => {
assistantDigestArchiveState.profile_scope = digestArchiveSavedDefaults.profile_scope || 'selected_profile';
assistantDigestArchiveState.query_preset = digestArchiveSavedDefaults.query_preset || '';
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Clear Archive Filters',
onClick: () => {
assistantDigestArchiveState = {
profile_key: selectedProfileKey,
profile_scope: 'selected_profile',
query_preset: '',
preferred_history_kind: '',
digest_mode: '',
query_text: '',
created_after: '',
created_before: '',
limit: 12,
next_offset: 0,
selected_left_id: null,
selected_right_id: null,
pinned_baseline_id: null,
};
window.__assistantDigestArchiveResponse = null;
window.__assistantDigestArchiveCompare = null;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
])
);
digestArchivePanel.appendChild(
buildInfoGrid([
['archive query profile', assistantDigestArchiveState.profile_key || selectedProfileKey],
['archive profile scope', assistantDigestArchiveState.profile_scope || digestArchiveSavedDefaults.profile_scope || 'selected_profile'],
['archive preset', assistantDigestArchiveState.query_preset || digestArchiveSavedDefaults.query_preset || 'custom'],
['archive preset summary', digestArchiveData?.query_preset_summary || 'custom_filters'],
['saved archive defaults', `${digestArchiveSavedDefaults.profile_scope || 'selected_profile'} / ${digestArchiveSavedDefaults.query_preset || 'custom'}`],
['archive query mode', assistantDigestArchiveState.digest_mode || 'all'],
['archive query kind', assistantDigestArchiveState.preferred_history_kind || 'all'],
['archive query text', assistantDigestArchiveState.query_text || 'n/a'],
['archive created after', assistantDigestArchiveState.created_after || 'n/a'],
['archive created before', assistantDigestArchiveState.created_before || 'n/a'],
['archive trend', digestArchiveLongRangeSummary?.trend_status || 'n/a'],
['archive trend story', digestArchiveLongRangeSummary?.trend_story || 'n/a'],
['archive 7d / 30d', `${digestArchiveLongRangeSummary?.recent_7d_count ?? 0} / ${digestArchiveLongRangeSummary?.recent_30d_count ?? 0}`],
['archive span days', String(digestArchiveLongRangeSummary?.covered_day_span ?? 0)],
['archive baseline', String(assistantDigestArchiveState.pinned_baseline_id ?? digestArchiveBaselineSummary?.baseline_snapshot_id ?? 'n/a')],
['archive baseline persistence', digestArchiveBaselineSummary?.persistence_status || digestPreferenceProfile?.archive_baselines?.status || 'n/a'],
['archive baseline delta', digestArchiveBaselineSummary?.baseline_delta_status || 'n/a'],
['archive baseline delta story', digestArchiveBaselineSummary?.baseline_delta_story || 'n/a'],
['archive baseline prompt', digestArchiveBaselineSummary?.suggested_compare_prompt || 'n/a'],
['archive next offset', String(digestArchiveData?.next_offset ?? assistantDigestArchiveState.next_offset ?? 0)],
['compare left snapshot', String(assistantDigestArchiveState.selected_left_id ?? 'n/a')],
['compare right snapshot', String(assistantDigestArchiveState.selected_right_id ?? 'n/a')],
])
);
if (digestArchiveRankedAggregation) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['archive top profile', digestArchiveRankedAggregation.top_profile?.value || 'n/a'],
['archive top kind', digestArchiveRankedAggregation.top_history_kind?.value || 'n/a'],
['archive aggregation story', digestArchiveRankedAggregation.aggregation_story || 'n/a'],
])
);
const digestRankGrid = createElement('div', 'cards assistant-tight-grid');
(digestArchiveRankedAggregation.profile_rankings || []).slice(0, 3).forEach((item) => {
digestRankGrid.appendChild(
buildItemCard(
`Profile ${item.value || 'n/a'}`,
String(item.count ?? 0),
[['count', String(item.count ?? 0)]]
)
);
});
(digestArchiveRankedAggregation.history_kind_rankings || []).slice(0, 3).forEach((item) => {
digestRankGrid.appendChild(
buildItemCard(
`Kind ${item.value || 'n/a'}`,
String(item.count ?? 0),
[['count', String(item.count ?? 0)]]
)
);
});
decisionAssistantPanel.appendChild(digestRankGrid);
}
decisionAssistantPanel.appendChild(digestArchivePanel);
if (digestArchiveCompare?.status === 'active') {
const digestCompareLeft = digestArchiveCompare.left || {};
const digestCompareRight = digestArchiveCompare.right || {};
decisionAssistantPanel.appendChild(
buildInfoGrid([
['compare left', formatTimestamp(digestArchiveCompare.left_created_ts || digestCompareLeft.created_ts)],
['compare right', formatTimestamp(digestArchiveCompare.right_created_ts || digestCompareRight.created_ts)],
['changed fields', formatList(digestArchiveCompare.changed_fields || [])],
['added titles', formatList(digestArchiveCompare.added_titles || [])],
['removed titles', formatList(digestArchiveCompare.removed_titles || [])],
['reminder delta', String(digestArchiveCompare.count_delta?.reminder_count ?? 0)],
['high value delta', String(digestArchiveCompare.count_delta?.high_value_reminder_count ?? 0)],
['left body', digestCompareLeft.summary_body || 'n/a'],
['right body', digestCompareRight.summary_body || 'n/a'],
])
);
}
if (assistantDigestArchiveLastExport?.selection_provenance_summary) {
const exportProvenance = assistantDigestArchiveLastExport.selection_provenance_summary;
decisionAssistantPanel.appendChild(
buildInfoGrid([
['export provenance', exportProvenance.selection_label || 'n/a'],
['export scope', exportProvenance.export_scope || 'n/a'],
['selected snapshots', formatList((exportProvenance.selected_snapshot_ids || []).map((item) => String(item)))],
['active filters', String(exportProvenance.active_filter_count ?? 0)],
['baseline snapshot', String(exportProvenance.baseline_snapshot_id ?? 'n/a')],
['selection fingerprint', exportProvenance.selection_fingerprint || 'n/a'],
])
);
}
if (assistantDigestArchiveLastExport?.bundle_manifest) {
const bundleManifest = assistantDigestArchiveLastExport.bundle_manifest;
decisionAssistantPanel.appendChild(
buildInfoGrid([
['bundle manifest', bundleManifest.manifest_label || 'n/a'],
['manifest version', bundleManifest.manifest_version || 'n/a'],
['manifest sections', formatList(bundleManifest.included_sections || [])],
['manifest section count', String(bundleManifest.included_section_count ?? 0)],
['manifest story', bundleManifest.manifest_story || 'n/a'],
])
);
}
if (digestArchiveData?.items?.length) {
const archiveGrid = createElement('div', 'cards assistant-tight-grid');
(digestArchiveData.items || []).forEach((item) => {
const isLeft = String(item.snapshot_id || '') === String(assistantDigestArchiveState.selected_left_id || '');
const isRight = String(item.snapshot_id || '') === String(assistantDigestArchiveState.selected_right_id || '');
const baselineId = assistantDigestArchiveState.pinned_baseline_id || digestArchiveBaselineSummary?.baseline_snapshot_id;
const isBaseline = String(item.snapshot_id || '') === String(baselineId || '');
const compareLabel = isBaseline ? 'baseline_pinned' : (isLeft ? 'left_selected' : (isRight ? 'right_selected' : (item.digest_mode || 'digest')));
const actions = [
{
label: isLeft ? 'Left Selected' : 'Select Left',
onClick: async () => {
selectAssistantDigestArchiveSnapshot('left', item.snapshot_id);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: isRight ? 'Right Selected' : 'Select Right',
onClick: async () => {
selectAssistantDigestArchiveSnapshot('right', item.snapshot_id);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: isBaseline ? 'Baseline Pinned' : 'Pin Baseline',
onClick: async () => {
assistantDigestArchiveState.pinned_baseline_id = item.snapshot_id;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Save This Baseline',
onClick: async () => {
assistantDigestArchiveState.pinned_baseline_id = item.snapshot_id;
await persistAssistantArchiveBaselinesServer({
profileKey: assistantDigestArchiveState.profile_key || selectedProfileKey,
digestSnapshotId: item.snapshot_id,
});
await refreshDashboard();
},
},
{
label: 'Compare To Baseline',
onClick: async () => {
const pinnedId = assistantDigestArchiveState.pinned_baseline_id || digestArchiveBaselineSummary?.baseline_snapshot_id;
if (!pinnedId || String(pinnedId) === String(item.snapshot_id || '')) return;
assistantDigestArchiveState.selected_left_id = item.snapshot_id;
assistantDigestArchiveState.selected_right_id = pinnedId;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
];
const card = buildItemCard(
item.top_summary || item.top_opportunity_title || 'digest snapshot',
compareLabel,
[
['snapshot', String(item.snapshot_id ?? 'n/a')],
['profile', item.profile_key || 'n/a'],
['time', formatTimestamp(item.created_ts)],
['history kind', item.preferred_history_kind || 'n/a'],
['summary body', item.summary_body || 'n/a'],
['next action', item.next_digest_action_label || 'n/a'],
['high value reminders', String(item.high_value_reminder_count ?? 0)],
['reminders', String(item.reminder_count ?? 0)],
['titles', formatList(item.reminder_titles || [])],
],
actions
);
if (isLeft || isRight || isBaseline) card.classList.add('assistant-compare-selected');
archiveGrid.appendChild(
card
);
});
decisionAssistantPanel.appendChild(archiveGrid);
}
if (reminderCards.length) {
const reminderGrid = createElement('div', 'cards assistant-tight-grid');
reminderCards.forEach((item) => {
reminderGrid.appendChild(
buildItemCard(
item.title || 'reminder',
item.severity || 'info',
[
['message', item.message || 'n/a'],
['source', item.source || 'n/a'],
['importance', String(item.importance_score ?? 'n/a')],
['template', item.importance_template || 'n/a'],
['high value', String(Boolean(item.high_value))],
['high value reason', item.high_value_reason || 'n/a'],
['focus related', String(Boolean(item.focus_related))],
['focus candidate', String(item.focus_candidate_id ?? 'n/a')],
]
)
);
});
decisionAssistantPanel.appendChild(reminderGrid);
}
if (digestHistoryGroups.length) {
const recommendedKind = digestSurface?.history_summary?.recommended_kind || 'all';
const groupKinds = digestHistoryGroups.map((item) => item.kind);
if (activeHistoryFilter !== 'all' && !groupKinds.includes(activeHistoryFilter)) {
persistAssistantHistoryKindFilter(recommendedKind);
}
const historyFilterBar = buildActionBar([
{
label: 'All History',
onClick: () => {
persistAssistantHistoryKindFilter('all');
updateAssistantPreferenceDraft({ preferred_history_kind: 'all' });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
...(recommendedKind && recommendedKind !== 'all'
? [{
label: `Recommended ${recommendedKind}`,
onClick: () => {
persistAssistantHistoryKindFilter(recommendedKind);
updateAssistantPreferenceDraft({ preferred_history_kind: recommendedKind });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}]
: []),
...digestHistoryGroups.map((item) => ({
label: `${item.kind} (${item.count})${item.recommended ? ' *' : ''}`,
onClick: () => {
persistAssistantHistoryKindFilter(item.kind || 'all');
updateAssistantPreferenceDraft({ preferred_history_kind: item.kind || 'all' });
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
})),
]);
decisionAssistantPanel.appendChild(historyFilterBar);
decisionAssistantPanel.appendChild(
buildInfoGrid([
['active history focus', activeHistoryFilter || 'all'],
['recommended history focus', recommendedKind || 'n/a'],
])
);
const groupGrid = createElement('div', 'cards assistant-history-grid');
const visibleGroups = activeHistoryFilter === 'all'
? digestHistoryGroups
: digestHistoryGroups.filter((item) => String(item.kind || '') === activeHistoryFilter);
visibleGroups.forEach((item) => {
const card = buildItemCard(
item.recommended ? `Recommended ${item.kind || 'history'}` : `History: ${item.kind || 'history'}`,
item.group_status || String(item.count ?? 0),
[
['headline', item.headline || 'n/a'],
['browser rank', String(item.browser_rank ?? 'n/a')],
['filter label', item.filter_label || 'n/a'],
['browser prompt', item.browser_prompt || 'n/a'],
['review-back priority', item.review_back_priority || 'n/a'],
['latest', formatTimestamp(item.latest_ts)],
['latest item', item.latest_title || 'n/a'],
['age band', item.age_band || 'n/a'],
['staleness', item.staleness_hint || 'n/a'],
['refresh', item.refresh_prompt || 'n/a'],
['refresh confirmation', item.refresh_confirmation_status || 'n/a'],
['confirmation prompt', item.refresh_confirmation_prompt || 'n/a'],
['freshness proof', item.freshness_proof_status || 'n/a'],
['proof detail', item.freshness_proof_detail || 'n/a'],
['proof age trend', item.proof_age_trend || 'n/a'],
['proof escalation', item.proof_escalation_level || 'n/a'],
['proof escalation prompt', item.proof_escalation_prompt || 'n/a'],
['proof follow-up', item.proof_follow_up_state || 'n/a'],
['proof follow-up action', item.proof_follow_up_action_label || 'n/a'],
['proof resolved state', item.proof_resolved_state || 'n/a'],
['proof follow-up age', item.proof_follow_up_age_band || 'n/a'],
['proof stale queue', String(Boolean(item.proof_follow_up_stale_queue))],
['proof resolution history', formatList((item.proof_resolution_history || []).map((row) => `${row.proof_label || row.state}: ${formatTimestamp(row.ts)}`))],
['proof SLA status', item.proof_resolution_sla_status || 'n/a'],
['proof SLA', formatDurationSeconds(item.proof_resolution_sla_seconds)],
['proof SLA prompt', item.proof_resolution_sla_prompt || 'n/a'],
['SLA backlog route', item.proof_sla_backlog_route || 'n/a'],
['SLA backlog priority', item.proof_sla_backlog_priority || 'n/a'],
['freshness debt', String(item.freshness_debt_score ?? 0)],
['freshness debt trend', item.freshness_debt_trend || 'n/a'],
['SLA recovery', item.sla_recovery_recommendation?.label || 'n/a'],
['SLA recovery prompt', item.sla_recovery_recommendation?.prompt || 'n/a'],
['stale suppression', item.repeated_stale_proof_suppression || 'n/a'],
['latest proof trail', item.latest_confirmation_trail_item?.proof_label || 'n/a'],
['proof trail items', formatList((item.refresh_confirmation_trail || []).map((row) => `${row.title || row.kind}: ${row.proof_label}`))],
['refresh evidence', item.refresh_evidence_anchor || 'n/a'],
['evidence path', item.refresh_evidence_path || 'n/a'],
['count', String(item.count ?? 0)],
['items', formatList((item.items || []).map((row) => row.title || row.kind || 'item'))],
],
[{
label: item.refresh_action_label || item.action_label || 'Review Group',
onClick: () => {
persistAssistantHistoryKindFilter(item.kind || 'all');
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}]
);
if (item.recommended) {
card.classList.add('assistant-history-recommended');
}
groupGrid.appendChild(card);
});
if (visibleGroups.length) {
decisionAssistantPanel.appendChild(groupGrid);
} else {
decisionAssistantPanel.appendChild(createElement('div', 'empty-state', 'No history items match the current digest filter.'));
}
}
if (reviewEntrypoints) {
appendSectionTitle(decisionAssistantPanel, 'Review Entry');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['review entrypoints', reviewEntrypoints.status || 'idle'],
['notes', String(reviewEntrypoints.note_count ?? 0)],
['focus candidate notes', String(reviewEntrypoints.focus_note_count ?? 0)],
['focus session', reviewEntrypoints.focus_session_code || 'n/a'],
['focus model', reviewEntrypoints.focus_model_code || 'n/a'],
['latest note author', reviewEntrypoints.latest_note_author || 'n/a'],
['latest note time', formatTimestamp(reviewEntrypoints.latest_note_ts)],
['focus latest note', formatTimestamp(reviewEntrypoints.focus_latest_note_ts)],
['focus note prompt', reviewEntrypoints.focus_note_prompt || 'n/a'],
['journal entries', String(reviewEntrypoints.journal_entry_count ?? 0)],
['review queue', String(reviewEntrypoints.review_queue_count ?? 0)],
['next review action', reviewEntrypoints.next_review_action || 'n/a'],
['review action queue', String(reviewEntrypoints.review_entry_action_queue_count ?? 0)],
['next review queue action', reviewEntrypoints.next_review_entry_action?.label || 'n/a'],
['next review queue prompt', reviewEntrypoints.next_review_entry_action?.prompt || 'n/a'],
['recommended template', reviewEntrypoints.recommended_template_id || 'n/a'],
['recommended label', reviewEntrypoints.template_summary?.recommended_label || 'n/a'],
['recommended priority', reviewEntrypoints.template_summary?.recommended_priority || 'n/a'],
['recommended reason', reviewEntrypoints.template_summary?.recommended_reason || 'n/a'],
['recommended reuse hint', reviewEntrypoints.template_summary?.recommended_reuse_hint || 'n/a'],
['template reuse status', reviewEntrypoints.template_reuse_metrics?.reuse_status || 'n/a'],
['template notes saved', String(reviewEntrypoints.template_reuse_metrics?.assistant_template_note_count ?? 0)],
['recommended reuse count', String(reviewEntrypoints.template_reuse_metrics?.recommended_reuse_count ?? 0)],
['recommended last used', formatTimestamp(reviewEntrypoints.template_reuse_metrics?.recommended_last_used_ts)],
['latest template note', formatTimestamp(reviewEntrypoints.template_reuse_metrics?.latest_template_note_ts)],
['recommended outcome', reviewEntrypoints.template_reuse_metrics?.recommended_outcome_status || 'n/a'],
['recommended usefulness', formatPercent(reviewEntrypoints.template_reuse_metrics?.recommended_usefulness_score)],
['feedback tuned template', reviewEntrypoints.template_reuse_metrics?.feedback_tuned_template_id || 'n/a'],
['recommendation tuning', reviewEntrypoints.template_reuse_metrics?.recommendation_tuning_status || 'n/a'],
['useful feedback', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.useful_feedback_count ?? 0)],
['actionable feedback', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.actionable_feedback_count ?? 0)],
['misleading feedback', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.misleading_feedback_count ?? 0)],
['feedback trend', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.feedback_trend_status || 'n/a'],
['feedback trend samples', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.feedback_trend_history_count ?? 0)],
['negative guardrails', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.negative_feedback_guardrail_count ?? 0)],
['guardrail templates', formatList(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.negative_feedback_guardrail_template_ids || [])],
['guardrail resolution queue', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.guardrail_resolution_count ?? 0)],
['preference recovery queue', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.preference_recovery_count ?? 0)],
['next preference recovery', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.next_preference_recovery_template_id || 'n/a'],
['guardrail audit trail', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.guardrail_audit_trail_count ?? 0)],
['recovery recommendations', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.preference_recovery_recommendation_count ?? 0)],
['next recovery action', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.next_preference_recovery_action || 'n/a'],
['next recovery prompt', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.next_preference_recovery_prompt || 'n/a'],
['audit filters', formatJsonInline(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.guardrail_audit_filter_counts || {})],
['filtered audit trail', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.guardrail_audit_filtered_count ?? 0)],
['audit lane groups', formatList((reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.template_audit_lane_groups || []).map((item) => `${item.label || item.audit_lane_group}: ${item.count ?? 0}`))],
['recovery shortcuts', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.recovery_action_shortcut_count ?? 0)],
['next recovery shortcut', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.next_recovery_action_shortcut?.label || 'n/a'],
['audit lane recommendations', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.template_audit_lane_recommendation_count ?? 0)],
['next audit lane prompt', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.next_shortcut_outcome_prompt || 'n/a'],
['shortcut telemetry', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.shortcut_outcome_telemetry_count ?? 0)],
['shortcut telemetry states', formatJsonInline(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.shortcut_outcome_status_counts || {})],
['preferred template decay', reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.preferred_template_decay_status || 'n/a'],
['preferred decay templates', formatList(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.preferred_template_decay_template_ids || [])],
['max preference decay', formatPercent(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.preferred_template_decay_max)],
['rated templates', String(reviewEntrypoints.template_reuse_metrics?.template_feedback_aggregation?.rated_template_count ?? 0)],
['template outcome avg', formatPercent(reviewEntrypoints.template_reuse_metrics?.template_outcome_summary?.average_usefulness_score)],
['template feedback gaps', String(reviewEntrypoints.template_reuse_metrics?.template_outcome_summary?.feedback_gap_count ?? 0)],
['template feedback needed', String(reviewEntrypoints.template_reuse_metrics?.template_outcome_summary?.feedback_capture_needed_count ?? 0)],
['best outcome template', reviewEntrypoints.template_reuse_metrics?.template_outcome_summary?.best_template_id || 'n/a'],
['feedback loop status', reviewEntrypoints.template_reuse_metrics?.feedback_loop_summary?.status || 'n/a'],
['next feedback template', reviewEntrypoints.template_reuse_metrics?.feedback_loop_summary?.next_feedback_template_id || 'n/a'],
['next feedback prompt', reviewEntrypoints.template_reuse_metrics?.feedback_loop_summary?.next_feedback_prompt || 'n/a'],
['template priorities', formatJsonInline(reviewEntrypoints.template_summary?.priorities || {})],
['handoff lanes', formatJsonInline(reviewEntrypoints.review_entry_handoff_summary?.lane_counts || {})],
['review handoff prompt', reviewEntrypoints.review_entry_handoff_summary?.next_handoff_prompt || 'n/a'],
])
);
if (workflowArchiveBridgeContext) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['archive bridge', workflowArchiveBridgeContext.bridge_mode || 'n/a'],
['archive snapshot', String(workflowArchiveBridgeContext.snapshot_id ?? 'n/a')],
['archive session', workflowArchiveBridgeContext.session_code || 'n/a'],
['archive next phase', workflowArchiveBridgeContext.next_phase || 'n/a'],
['archive artifact', workflowArchiveBridgeContext.next_artifact_kind || 'n/a'],
['archive prompt', workflowArchiveBridgeContext.next_artifact_prompt || 'n/a'],
])
);
}
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Open Notes',
onClick: () => prefillOperatorNote(''),
},
{
label: 'Prefill Focus Note',
onClick: () => prefillOperatorNote(
reviewEntrypoints.focus_note_prefill || '',
{
candidate_id: reviewEntrypoints.focus_candidate_id,
session_code: reviewEntrypoints.focus_session_code,
model_code: reviewEntrypoints.focus_model_code,
},
),
},
{
label: 'Open Review',
onClick: () => revealPanel(postTradeReviewPanel),
},
{
label: 'Generate Journal',
onClick: () => runAction('/trading/journal/generate', {}),
},
...(workflowArchiveBridgeContext ? [{
label: 'Clear Archive Bridge',
onClick: () => {
setWorkflowArchiveBridgeContext(null);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}] : []),
])
);
if (reviewEntrypoints.review_entry_action_queue?.length) {
const reviewActionGrid = createElement('div', 'cards assistant-tight-grid');
(reviewEntrypoints.review_entry_action_queue || []).forEach((item) => {
reviewActionGrid.appendChild(
buildItemCard(
item.label || 'review action',
item.priority || item.source || 'n/a',
[
['source', item.source || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(reviewActionGrid);
}
const noteTemplates = reviewEntrypoints.note_templates || [];
if (noteTemplates.length) {
const recommendedTemplate = noteTemplates.find((item) => item.template_id === reviewEntrypoints.recommended_template_id) || noteTemplates[0];
const tunedTemplateId = reviewEntrypoints.template_reuse_metrics?.feedback_tuned_template_id || reviewEntrypoints.recommended_template_id;
const tunedTemplate = noteTemplates.find((item) => item.template_id === tunedTemplateId) || recommendedTemplate;
const templateGrid = createElement('div', 'cards assistant-tight-grid');
noteTemplates.forEach((item) => {
const isRecommended = item.template_id === reviewEntrypoints.recommended_template_id;
templateGrid.appendChild(
buildItemCard(
isRecommended ? `Recommended: ${item.label || 'Template'}` : (item.label || 'Template'),
item.priority || 'medium',
[
['reason', item.reason || 'n/a'],
['scope', item.note_scope || 'workbench'],
['tags', formatList(item.tags || [])],
['context', formatList(item.context_items || [])],
['carry-over', formatList(item.carry_over_context || [])],
['reuse count', String(item.reuse_count ?? 0)],
['reuse status', item.reuse_status || 'n/a'],
['last used', formatTimestamp(item.last_used_ts)],
['outcome', item.outcome_status || 'n/a'],
['usefulness', formatPercent(item.usefulness_score)],
['outcome evidence', formatList(item.outcome_evidence || [])],
['feedback loop', item.feedback_loop_status || 'n/a'],
['feedback prompt', item.feedback_prompt || 'n/a'],
['negative guardrail', item.negative_feedback_guardrail || 'n/a'],
['guardrail prompt', item.negative_feedback_guardrail_prompt || 'n/a'],
['guardrail resolution', item.guardrail_resolution_status || 'n/a'],
['guardrail resolution prompt', item.guardrail_resolution_prompt || 'n/a'],
['preference decay', formatPercent(item.preferred_template_decay)],
['decay reason', item.preferred_template_decay_reason || 'n/a'],
['preference recovery', item.preference_recovery_status || 'n/a'],
['recovery prompt', item.preference_recovery_prompt || 'n/a'],
['recovery recommendation', item.preference_recovery_recommendation?.action || 'n/a'],
['audit lane', item.audit_lane_group || 'n/a'],
['audit lane rank', String(item.audit_lane_rank ?? 'n/a')],
['audit lane recommendation', item.audit_lane_recommendation?.action || 'n/a'],
['audit lane prompt', item.audit_lane_recommendation?.prompt || 'n/a'],
['recovery shortcuts', formatList((item.recovery_action_shortcuts || []).map((row) => row.label || row.action_id))],
['shortcut telemetry', formatList((item.shortcut_outcome_telemetry || []).map((row) => `${row.label || row.action_id}: ${row.telemetry_status}`))],
['audit filter', item.guardrail_audit_filter || 'n/a'],
['audit filter reason', item.guardrail_audit_filter_reason || 'n/a'],
['guardrail audit trail', formatList((item.guardrail_audit_trail || []).map((row) => `${row.label || row.signal}: ${row.resolution_status}`))],
['filtered audit trail', formatList((item.guardrail_audit_filtered_trail || []).map((row) => `${row.label || row.signal}: ${row.resolution_status}`))],
['feedback trend history', formatList((item.feedback_trend_history || []).map((row) => `${row.label || row.signal}: ${formatTimestamp(row.created_ts)}`))],
],
[
{
label: 'Use',
onClick: () => prefillOperatorNote(item.body || ''),
},
{
label: 'Save',
onClick: () => saveOperatorTemplateNote(item),
},
...(item.feedback_actions || []).map((action) => ({
label: action.label || action.outcome || 'Feedback',
onClick: () => saveOperatorTemplateFeedback(item, action.outcome || action.action_id || 'useful'),
})),
],
[item.body || 'n/a', item.follow_up_prompt || '', item.reuse_hint || ''].filter(Boolean).join(' | '),
)
);
});
decisionAssistantPanel.appendChild(templateGrid);
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Use Recommended',
onClick: () => prefillOperatorNote(recommendedTemplate?.body || ''),
},
{
label: 'Save Recommended',
onClick: () => saveOperatorTemplateNote(recommendedTemplate),
},
{
label: 'Use Tuned',
onClick: () => prefillOperatorNote(tunedTemplate?.body || ''),
},
{
label: 'Save Tuned',
onClick: () => saveOperatorTemplateNote(tunedTemplate),
},
])
);
const templateBar = buildActionBar(
noteTemplates.map((item) => ({
label: item.template_id === reviewEntrypoints.recommended_template_id
? `${item.label || 'Use Template'}`
: (item.label || 'Use Template'),
onClick: () => prefillOperatorNote(item.body || ''),
}))
);
decisionAssistantPanel.appendChild(templateBar);
const quickSaveBar = buildActionBar(
noteTemplates.map((item) => ({
label: `Save ${item.label || 'Template'}`,
onClick: () => saveOperatorTemplateNote(item),
}))
);
decisionAssistantPanel.appendChild(quickSaveBar);
}
}
if (workflowDigest.length) {
appendSectionTitle(decisionAssistantPanel, 'Workflow');
if (workflowRhythmSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow rhythm', workflowRhythmSummary.status || 'idle'],
['rhythm phases', String(workflowRhythmSummary.phase_count ?? 0)],
['rhythm checks', String(workflowRhythmSummary.check_count ?? 0)],
['rhythm complete', String(workflowRhythmSummary.completed_count ?? 0)],
['rhythm pending', String(workflowRhythmSummary.pending_count ?? 0)],
['next rhythm phase', workflowRhythmSummary.next_phase || 'n/a'],
['next rhythm action', workflowRhythmSummary.next_action || 'n/a'],
['cadence', formatList(workflowRhythmSummary.cadence || [])],
])
);
}
if (workflowSessionCompletionSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['session tasks', workflowSessionCompletionSummary.status || 'idle'],
['session', workflowSessionCompletionSummary.current_session || 'n/a'],
['task count', String(workflowSessionCompletionSummary.task_count ?? 0)],
['tasks complete', String(workflowSessionCompletionSummary.completed_task_count ?? 0)],
['tasks in progress', String(workflowSessionCompletionSummary.in_progress_task_count ?? 0)],
['tasks pending', String(workflowSessionCompletionSummary.pending_task_count ?? 0)],
['next session task', workflowSessionCompletionSummary.next_task_label || 'n/a'],
['next session prompt', workflowSessionCompletionSummary.next_task_prompt || 'n/a'],
['completion ratio', formatPercent(workflowSessionCompletionSummary.completion_ratio)],
])
);
}
if (summary.workflow_artifact_summary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow artifacts', summary.workflow_artifact_summary.status || 'idle'],
['artifact count', String(summary.workflow_artifact_summary.artifact_count ?? 0)],
['artifacts ready', String(summary.workflow_artifact_summary.ready_for_handoff_count ?? 0)],
['artifacts updating', String(summary.workflow_artifact_summary.needs_update_count ?? 0)],
['artifacts pending', String(summary.workflow_artifact_summary.pending_capture_count ?? 0)],
['next artifact', summary.workflow_artifact_summary.next_artifact_kind || 'n/a'],
['next artifact prompt', summary.workflow_artifact_summary.next_artifact_prompt || 'n/a'],
['workflow archive', String(summary.workflow_artifact_summary.workflow_history_archive_count ?? 0)],
['workflow archive review', summary.workflow_artifact_summary.next_workflow_history_review || 'n/a'],
['workflow day groups', String(workflowArchiveData?.daily_group_count ?? workflowArchiveDailyGroups.length ?? 0)],
['workflow session groups', String(workflowArchiveData?.session_group_count ?? workflowArchiveSessionGroups.length ?? 0)],
['workflow compare', workflowArchiveCompare?.status || 'idle'],
['workflow compare summary', workflowArchiveCompare?.summary || 'n/a'],
['workflow persistence', summary.workflow_artifact_summary.workflow_persistence_status || 'n/a'],
])
);
}
if (workflowArchiveBridgeSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow bridge', workflowArchiveBridgeSummary.status || 'idle'],
['bridge targets', String(workflowArchiveBridgeSummary.bridge_target_count ?? 0)],
['replay ready', String(workflowArchiveBridgeSummary.replay_ready_count ?? 0)],
['note ready', String(workflowArchiveBridgeSummary.note_ready_count ?? 0)],
['handoff ready', String(workflowArchiveBridgeSummary.handoff_ready_count ?? 0)],
['bridge snapshot', String(workflowArchiveBridgeSummary.latest_snapshot_id ?? 'n/a')],
['bridge session', workflowArchiveBridgeSummary.latest_session || 'n/a'],
['bridge next phase', workflowArchiveBridgeSummary.latest_next_phase || 'n/a'],
['bridge replay prompt', workflowArchiveBridgeSummary.next_replay_prompt || 'n/a'],
['bridge handoff prompt', workflowArchiveBridgeSummary.next_handoff_prompt || 'n/a'],
])
);
}
if (workflowArchiveBridgePersistenceSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['bridge persistence', workflowArchiveBridgePersistenceSummary.status || 'idle'],
['bridge saved at', formatTimestamp(workflowArchiveBridgePersistenceSummary.updated_ts)],
['bridge saved preset', workflowArchiveBridgePersistenceSummary.query_context?.query_preset || 'custom'],
['bridge saved scope', workflowArchiveBridgePersistenceSummary.query_context?.profile_scope || 'selected_profile'],
['bridge saved handoff', workflowArchiveBridgePersistenceSummary.handoff_packet_starter?.headline || 'n/a'],
['bridge saved replay', workflowArchiveBridgePersistenceSummary.replay_note_bridge_summary?.note_title || 'n/a'],
['bridge saved bundle', workflowArchiveBridgePersistenceSummary.artifact_bundle_summary?.starter_export_prompt || 'n/a'],
['bridge saved compare note', workflowArchiveBridgePersistenceSummary.compare_writeback_summary?.note_title || 'n/a'],
['bridge compare note at', formatTimestamp(workflowArchiveBridgePersistenceSummary.compare_writeback_summary?.created_ts)],
])
);
if (workflowArchiveBridgePersistenceSummary.compare_writeback_summary?.note_body) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Prefill Saved Compare Note',
onClick: () => prefillOperatorNote(
workflowArchiveBridgePersistenceSummary.compare_writeback_summary?.note_body || '',
workflowArchiveBridgeContext || null,
),
},
])
);
}
}
if (workflowArchiveBridgeContext) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Open Bridged Replay',
onClick: () => revealAssistantSection('Setup Replay'),
},
{
label: 'Prefill Bridged Note',
onClick: () => prefillOperatorNote(buildWorkflowArchiveBridgeNote(workflowArchiveBridgeContext), workflowArchiveBridgeContext),
},
{
label: 'Clear Workflow Bridge',
onClick: () => {
setWorkflowArchiveBridgeContext(null);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
])
);
}
const workflowArchivePanel = createElement('div', 'assistant-archive-panel');
const workflowArchiveControls = createElement('div', 'assistant-archive-controls');
const workflowProfileField = createElement('label', 'assistant-preference-field');
workflowProfileField.appendChild(createElement('span', 'metric', 'Workflow Profile'));
const workflowProfileInput = createElement('input', 'assistant-preference-input');
workflowProfileInput.type = 'text';
workflowProfileInput.value = assistantWorkflowArchiveState.profile_key || selectedProfileKey;
workflowProfileField.appendChild(workflowProfileInput);
workflowArchiveControls.appendChild(workflowProfileField);
const workflowScopeField = createElement('label', 'assistant-preference-field');
workflowScopeField.appendChild(createElement('span', 'metric', 'Profile Scope'));
const workflowScopeSelect = createElement('select', 'assistant-preference-input');
['selected_profile', 'all_profiles'].forEach((scope) => {
const option = createElement('option', '', scope);
option.value = scope;
option.selected = scope === (assistantWorkflowArchiveState.profile_scope || workflowArchiveSavedDefaults.profile_scope || 'selected_profile');
workflowScopeSelect.appendChild(option);
});
workflowScopeField.appendChild(workflowScopeSelect);
workflowArchiveControls.appendChild(workflowScopeField);
const workflowPresetField = createElement('label', 'assistant-preference-field');
workflowPresetField.appendChild(createElement('span', 'metric', 'Query Preset'));
const workflowPresetSelect = createElement('select', 'assistant-preference-input');
[{ preset_id: '', label: 'custom' }, ...((workflowArchiveData?.available_query_presets || []))].forEach((preset) => {
const option = createElement('option', '', preset.label || preset.preset_id || 'custom');
option.value = preset.preset_id || '';
option.selected = (preset.preset_id || '') === (assistantWorkflowArchiveState.query_preset || workflowArchiveSavedDefaults.query_preset || '');
workflowPresetSelect.appendChild(option);
});
workflowPresetField.appendChild(workflowPresetSelect);
workflowArchiveControls.appendChild(workflowPresetField);
const workflowSessionField = createElement('label', 'assistant-preference-field');
workflowSessionField.appendChild(createElement('span', 'metric', 'Current Session'));
const workflowSessionInput = createElement('input', 'assistant-preference-input');
workflowSessionInput.type = 'text';
workflowSessionInput.value = assistantWorkflowArchiveState.current_session || '';
workflowSessionField.appendChild(workflowSessionInput);
workflowArchiveControls.appendChild(workflowSessionField);
const workflowPhaseField = createElement('label', 'assistant-preference-field');
workflowPhaseField.appendChild(createElement('span', 'metric', 'Next Phase'));
const workflowPhaseSelect = createElement('select', 'assistant-preference-input');
['', 'pre_market', 'intraday', 'post_trade'].forEach((phase) => {
const option = createElement('option', '', phase || 'all');
option.value = phase;
option.selected = phase === (assistantWorkflowArchiveState.next_phase || '');
workflowPhaseSelect.appendChild(option);
});
workflowPhaseField.appendChild(workflowPhaseSelect);
workflowArchiveControls.appendChild(workflowPhaseField);
const workflowArtifactField = createElement('label', 'assistant-preference-field');
workflowArtifactField.appendChild(createElement('span', 'metric', 'Artifact Kind'));
const workflowArtifactInput = createElement('input', 'assistant-preference-input');
workflowArtifactInput.type = 'text';
workflowArtifactInput.value = assistantWorkflowArchiveState.next_artifact_kind || '';
workflowArtifactField.appendChild(workflowArtifactInput);
workflowArchiveControls.appendChild(workflowArtifactField);
const workflowSearchField = createElement('label', 'assistant-preference-field');
workflowSearchField.appendChild(createElement('span', 'metric', 'Search Text'));
const workflowSearchInput = createElement('input', 'assistant-preference-input');
workflowSearchInput.type = 'text';
workflowSearchInput.value = assistantWorkflowArchiveState.query_text || '';
workflowSearchInput.placeholder = 'phase, prompt, body...';
workflowSearchField.appendChild(workflowSearchInput);
workflowArchiveControls.appendChild(workflowSearchField);
const workflowAfterField = createElement('label', 'assistant-preference-field');
workflowAfterField.appendChild(createElement('span', 'metric', 'Created After'));
const workflowAfterInput = createElement('input', 'assistant-preference-input');
workflowAfterInput.type = 'datetime-local';
workflowAfterInput.value = assistantWorkflowArchiveState.created_after || '';
workflowAfterField.appendChild(workflowAfterInput);
workflowArchiveControls.appendChild(workflowAfterField);
const workflowBeforeField = createElement('label', 'assistant-preference-field');
workflowBeforeField.appendChild(createElement('span', 'metric', 'Created Before'));
const workflowBeforeInput = createElement('input', 'assistant-preference-input');
workflowBeforeInput.type = 'datetime-local';
workflowBeforeInput.value = assistantWorkflowArchiveState.created_before || '';
workflowBeforeField.appendChild(workflowBeforeInput);
workflowArchiveControls.appendChild(workflowBeforeField);
const workflowLimitField = createElement('label', 'assistant-preference-field');
workflowLimitField.appendChild(createElement('span', 'metric', 'Workflow Limit'));
const workflowLimitInput = createElement('input', 'assistant-preference-input');
workflowLimitInput.type = 'number';
workflowLimitInput.min = '1';
workflowLimitInput.max = '50';
workflowLimitInput.value = String(assistantWorkflowArchiveState.limit || 12);
workflowLimitField.appendChild(workflowLimitInput);
workflowArchiveControls.appendChild(workflowLimitField);
workflowArchivePanel.appendChild(workflowArchiveControls);
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Apply Workflow Filters',
onClick: async () => {
await fetchAssistantWorkflowArchive({
profile_key: workflowProfileInput.value || selectedProfileKey,
profile_scope: workflowScopeSelect.value || 'selected_profile',
query_preset: workflowPresetSelect.value || '',
current_session: workflowSessionInput.value || '',
next_phase: workflowPhaseSelect.value || '',
next_artifact_kind: workflowArtifactInput.value || '',
query_text: workflowSearchInput.value || '',
created_after: workflowAfterInput.value || '',
created_before: workflowBeforeInput.value || '',
limit: Number(workflowLimitInput.value || 12),
selected_left_id: assistantWorkflowArchiveState.selected_left_id,
selected_right_id: assistantWorkflowArchiveState.selected_right_id,
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Load More Workflow',
onClick: async () => {
await fetchAssistantWorkflowArchive({
append: true,
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: Number(assistantWorkflowArchiveState.limit || 12),
selected_left_id: assistantWorkflowArchiveState.selected_left_id,
selected_right_id: assistantWorkflowArchiveState.selected_right_id,
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Compare Selected Workflow',
onClick: async () => {
if (!assistantWorkflowArchiveState.selected_left_id || !assistantWorkflowArchiveState.selected_right_id) {
showErrorPanel('select_two_workflow_snapshots');
return;
}
await fetchAssistantWorkflowArchive({
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: Number(assistantWorkflowArchiveState.limit || 12),
});
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Export Workflow Results',
onClick: async () => {
const exportLimit = Math.max(Number(assistantWorkflowArchiveState.limit || 12), Number(workflowArchiveData?.items?.length || 0));
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: exportLimit,
offset: 0,
})}`);
assistantWorkflowArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || 'workflow-archive-export.json', exportPayload);
},
},
{
label: 'Export Workflow Compare',
onClick: async () => {
if (!assistantWorkflowArchiveState.selected_left_id || !assistantWorkflowArchiveState.selected_right_id) {
showErrorPanel('select_two_workflow_snapshots');
return;
}
const exportLimit = Math.max(Number(assistantWorkflowArchiveState.limit || 12), Number(workflowArchiveData?.items?.length || 0));
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: exportLimit,
offset: 0,
left_id: assistantWorkflowArchiveState.selected_left_id,
right_id: assistantWorkflowArchiveState.selected_right_id,
})}`);
assistantWorkflowArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || 'workflow-archive-compare-export.json', exportPayload);
},
},
{
label: 'Save Workflow Baseline',
onClick: async () => {
const baselineId = assistantWorkflowArchiveState.pinned_baseline_id || workflowArchiveBaselineSummary?.baseline_snapshot_id;
if (!baselineId) {
showErrorPanel('workflow_baseline_missing');
return;
}
await persistAssistantArchiveBaselinesServer({
profileKey: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
workflowSnapshotId: baselineId,
});
await refreshDashboard();
},
},
{
label: 'Save Workflow Defaults',
onClick: async () => {
const saved = await persistAssistantDigestPreferenceServer({
profileKey: selectedProfileKey,
digestMode: assistantPreferenceDraft?.digest_mode || digestPreferenceProfile?.persisted_digest_mode || 'all_reminders',
preferredHistoryKind: assistantPreferenceDraft?.preferred_history_kind === 'all'
? null
: (assistantPreferenceDraft?.preferred_history_kind || digestPreferenceProfile?.preferred_history_kind || null),
importanceThreshold: assistantPreferenceDraft?.importance_threshold || digestPreferenceProfile?.importance_threshold || 70,
payload: {
profile_label: assistantPreferenceDraft?.profile_label || digestPreferenceProfile?.profile_label || selectedProfileKey,
history_window_hours: assistantPreferenceDraft?.history_window_hours || digestPreferenceProfile?.history_window_hours || 24,
importance_templates: { ...((assistantPreferenceDraft && assistantPreferenceDraft.importance_templates) || {}) },
archive_defaults: mergeAssistantArchiveDefaults(summary, {
workflow: {
profile_scope: workflowScopeSelect.value || 'selected_profile',
query_preset: workflowPresetSelect.value || '',
},
}),
},
});
if (!saved) {
showErrorPanel('workflow_archive_defaults_save_failed');
return;
}
assistantPreferenceDraft = {
...(assistantPreferenceDraft || {}),
archive_defaults: mergeAssistantArchiveDefaults(summary, {
workflow: {
profile_scope: workflowScopeSelect.value || 'selected_profile',
query_preset: workflowPresetSelect.value || '',
},
}),
};
await refreshDashboard();
},
},
{
label: 'Use Saved Workflow Defaults',
onClick: () => {
assistantWorkflowArchiveState.profile_scope = workflowArchiveSavedDefaults.profile_scope || 'selected_profile';
assistantWorkflowArchiveState.query_preset = workflowArchiveSavedDefaults.query_preset || '';
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Clear Workflow Filters',
onClick: () => {
assistantWorkflowArchiveState = {
profile_key: selectedProfileKey,
profile_scope: 'selected_profile',
query_preset: '',
current_session: '',
next_phase: '',
next_artifact_kind: '',
query_text: '',
created_after: '',
created_before: '',
limit: 12,
next_offset: 0,
selected_left_id: null,
selected_right_id: null,
pinned_baseline_id: null,
};
window.__assistantWorkflowArchiveResponse = null;
window.__assistantWorkflowArchiveCompare = null;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
])
);
workflowArchivePanel.appendChild(
buildInfoGrid([
['workflow query profile', assistantWorkflowArchiveState.profile_key || selectedProfileKey],
['workflow profile scope', assistantWorkflowArchiveState.profile_scope || workflowArchiveSavedDefaults.profile_scope || 'selected_profile'],
['workflow preset', assistantWorkflowArchiveState.query_preset || workflowArchiveSavedDefaults.query_preset || 'custom'],
['workflow preset summary', workflowArchiveData?.query_preset_summary || 'custom_filters'],
['saved workflow defaults', `${workflowArchiveSavedDefaults.profile_scope || 'selected_profile'} / ${workflowArchiveSavedDefaults.query_preset || 'custom'}`],
['workflow query session', assistantWorkflowArchiveState.current_session || 'all'],
['workflow query phase', assistantWorkflowArchiveState.next_phase || 'all'],
['workflow query artifact', assistantWorkflowArchiveState.next_artifact_kind || 'all'],
['workflow query text', assistantWorkflowArchiveState.query_text || 'n/a'],
['workflow created after', assistantWorkflowArchiveState.created_after || 'n/a'],
['workflow created before', assistantWorkflowArchiveState.created_before || 'n/a'],
['workflow trend', workflowArchiveLongRangeSummary?.trend_status || 'n/a'],
['workflow trend story', workflowArchiveLongRangeSummary?.trend_story || 'n/a'],
['workflow 7d / 30d', `${workflowArchiveLongRangeSummary?.recent_7d_count ?? 0} / ${workflowArchiveLongRangeSummary?.recent_30d_count ?? 0}`],
['workflow span days', String(workflowArchiveLongRangeSummary?.covered_day_span ?? 0)],
['workflow baseline', String(assistantWorkflowArchiveState.pinned_baseline_id ?? workflowArchiveBaselineSummary?.baseline_snapshot_id ?? 'n/a')],
['workflow baseline persistence', workflowArchiveBaselineSummary?.persistence_status || digestPreferenceProfile?.archive_baselines?.status || 'n/a'],
['workflow baseline delta', workflowArchiveBaselineSummary?.baseline_delta_status || 'n/a'],
['workflow baseline delta story', workflowArchiveBaselineSummary?.baseline_delta_story || 'n/a'],
['workflow baseline prompt', workflowArchiveBaselineSummary?.suggested_compare_prompt || 'n/a'],
['workflow next offset', String(workflowArchiveData?.next_offset ?? assistantWorkflowArchiveState.next_offset ?? 0)],
['workflow compare left', String(assistantWorkflowArchiveState.selected_left_id ?? 'n/a')],
['workflow compare right', String(assistantWorkflowArchiveState.selected_right_id ?? 'n/a')],
])
);
if (assistantWorkflowArchiveLastExport?.selection_provenance_summary) {
const exportProvenance = assistantWorkflowArchiveLastExport.selection_provenance_summary;
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow export provenance', exportProvenance.selection_label || 'n/a'],
['workflow export scope', exportProvenance.export_scope || 'n/a'],
['workflow selected snapshots', formatList((exportProvenance.selected_snapshot_ids || []).map((item) => String(item)))],
['workflow active filters', String(exportProvenance.active_filter_count ?? 0)],
['workflow baseline snapshot', String(exportProvenance.baseline_snapshot_id ?? 'n/a')],
['selection fingerprint', exportProvenance.selection_fingerprint || 'n/a'],
])
);
}
if (assistantWorkflowArchiveLastExport?.bundle_manifest) {
const bundleManifest = assistantWorkflowArchiveLastExport.bundle_manifest;
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow bundle manifest', bundleManifest.manifest_label || 'n/a'],
['workflow manifest version', bundleManifest.manifest_version || 'n/a'],
['workflow manifest sections', formatList(bundleManifest.included_sections || [])],
['workflow manifest section count', String(bundleManifest.included_section_count ?? 0)],
['workflow manifest story', bundleManifest.manifest_story || 'n/a'],
])
);
}
if (workflowArchiveRankedAggregation) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow top profile', workflowArchiveRankedAggregation.top_profile?.value || 'n/a'],
['workflow top session', workflowArchiveRankedAggregation.top_session?.value || 'n/a'],
['workflow top phase', workflowArchiveRankedAggregation.top_phase?.value || 'n/a'],
['workflow aggregation story', workflowArchiveRankedAggregation.aggregation_story || 'n/a'],
])
);
const workflowRankGrid = createElement('div', 'cards assistant-tight-grid');
(workflowArchiveRankedAggregation.profile_rankings || []).slice(0, 2).forEach((item) => {
workflowRankGrid.appendChild(
buildItemCard(`Profile ${item.value || 'n/a'}`, String(item.count ?? 0), [['count', String(item.count ?? 0)]])
);
});
(workflowArchiveRankedAggregation.session_rankings || []).slice(0, 2).forEach((item) => {
workflowRankGrid.appendChild(
buildItemCard(`Session ${item.value || 'n/a'}`, String(item.count ?? 0), [['count', String(item.count ?? 0)]])
);
});
(workflowArchiveRankedAggregation.phase_rankings || []).slice(0, 2).forEach((item) => {
workflowRankGrid.appendChild(
buildItemCard(`Phase ${item.value || 'n/a'}`, String(item.count ?? 0), [['count', String(item.count ?? 0)]])
);
});
decisionAssistantPanel.appendChild(workflowRankGrid);
}
decisionAssistantPanel.appendChild(workflowArchivePanel);
if (workflowArchiveOperationsSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow operations', workflowArchiveOperationsSummary.status || 'idle'],
['operation snapshots', String(workflowArchiveOperationsSummary.snapshot_count ?? 0)],
['day groups', String(workflowArchiveOperationsSummary.day_group_count ?? 0)],
['session groups', String(workflowArchiveOperationsSummary.session_group_count ?? 0)],
['latest day group', workflowArchiveOperationsSummary.latest_group_date || 'n/a'],
['most active session', workflowArchiveOperationsSummary.most_active_session || 'n/a'],
['phase names', String(workflowArchiveOperationsSummary.phase_name_count ?? 0)],
['operations prompt', workflowArchiveOperationsSummary.next_operations_prompt || 'n/a'],
])
);
}
if (workflowArchiveLongRangeSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow long-range', workflowArchiveLongRangeSummary.status || 'idle'],
['workflow trend status', workflowArchiveLongRangeSummary.trend_status || 'n/a'],
['workflow 7d snapshots', String(workflowArchiveLongRangeSummary.recent_7d_count ?? 0)],
['workflow 30d snapshots', String(workflowArchiveLongRangeSummary.recent_30d_count ?? 0)],
['workflow 7d ready', String(workflowArchiveLongRangeSummary.recent_7d_ready_count ?? 0)],
['workflow 30d ready', String(workflowArchiveLongRangeSummary.recent_30d_ready_count ?? 0)],
['workflow sessions', String(workflowArchiveLongRangeSummary.distinct_session_count ?? 0)],
['workflow next long-range review', workflowArchiveLongRangeSummary.next_review_prompt || 'n/a'],
])
);
}
if (workflowArchiveBaselineSummary) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow baseline status', workflowArchiveBaselineSummary.status || 'idle'],
['workflow baseline latest', String(workflowArchiveBaselineSummary.latest_snapshot_id ?? 'n/a')],
['workflow baseline pinned', String(assistantWorkflowArchiveState.pinned_baseline_id ?? workflowArchiveBaselineSummary.baseline_snapshot_id ?? 'n/a')],
['workflow baseline session', workflowArchiveBaselineSummary.baseline_session || 'n/a'],
['workflow baseline phase', workflowArchiveBaselineSummary.baseline_next_phase || 'n/a'],
['workflow baseline prompt', workflowArchiveBaselineSummary.suggested_compare_prompt || 'n/a'],
])
);
}
if (workflowArchiveDriftReview) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow drift', workflowArchiveDriftReview.status || 'idle'],
['drift status', workflowArchiveDriftReview.drift_status || 'n/a'],
['drift left day', workflowArchiveDriftReview.left_group_date || 'n/a'],
['drift right day', workflowArchiveDriftReview.right_group_date || 'n/a'],
['changed phases', String(workflowArchiveDriftReview.changed_phase_count ?? 0)],
['session changed', workflowArchiveDriftReview.session_changed ? 'yes' : 'no'],
['next phase changed', workflowArchiveDriftReview.next_phase_changed ? 'yes' : 'no'],
['drift summary', workflowArchiveDriftReview.summary || 'n/a'],
['drift next prompt', workflowArchiveDriftReview.next_drift_prompt || 'n/a'],
])
);
}
if (workflowArchiveDailyGroups.length) {
const workflowDayGroupGrid = createElement('div', 'cards assistant-tight-grid');
workflowArchiveDailyGroups.forEach((item) => {
workflowDayGroupGrid.appendChild(
buildItemCard(
`Day Group: ${item.group_date || 'workflow'}`,
item.status || 'active',
[
['snapshots', String(item.snapshot_count ?? 0)],
['latest time', formatTimestamp(item.latest_created_ts)],
['sessions', formatList(item.sessions || [])],
['next phase', item.next_phase || 'n/a'],
['artifact counts', `${item.artifact_count ?? 0} / ${item.ready_for_handoff_count ?? 0} / ${item.needs_update_count ?? 0} / ${item.pending_capture_count ?? 0}`],
['phase names', formatList(item.phase_names || [])],
['workflow body', item.workflow_body || 'n/a'],
['next prompt', item.next_artifact_prompt || 'n/a'],
],
[
{
label: 'Export Day Bundle',
onClick: async () => {
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: workflowArchiveData?.item_count || assistantWorkflowArchiveState.limit || 12,
offset: 0,
group_date: item.group_date || '',
})}`);
assistantWorkflowArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || `workflow-day-group-${item.group_date || 'export'}.json`, exportPayload);
},
},
]
)
);
});
decisionAssistantPanel.appendChild(workflowDayGroupGrid);
}
if (workflowArchiveSessionGroups.length) {
const workflowSessionGroupGrid = createElement('div', 'cards assistant-tight-grid');
workflowArchiveSessionGroups.forEach((item) => {
workflowSessionGroupGrid.appendChild(
buildItemCard(
`Session Group: ${item.session_code || 'workflow'}`,
item.status || 'active',
[
['snapshots', String(item.snapshot_count ?? 0)],
['day count', String(item.day_count ?? 0)],
['latest time', formatTimestamp(item.latest_created_ts)],
['latest day group', item.latest_group_date || 'n/a'],
['latest next phase', item.latest_next_phase || 'n/a'],
['artifact counts', `${item.artifact_count ?? 0} / ${item.ready_for_handoff_count ?? 0} / ${item.needs_update_count ?? 0} / ${item.pending_capture_count ?? 0}`],
['phase names', formatList(item.phase_names || [])],
],
[
{
label: 'Export Session Bundle',
onClick: async () => {
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: workflowArchiveData?.item_count || assistantWorkflowArchiveState.limit || 12,
offset: 0,
session_group: item.session_code || '',
})}`);
assistantWorkflowArchiveLastExport = exportPayload;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
downloadJsonFile(exportPayload.export_name || `workflow-session-group-${item.session_code || 'export'}.json`, exportPayload);
},
},
]
)
);
});
decisionAssistantPanel.appendChild(workflowSessionGroupGrid);
}
if (workflowArchiveCompare?.status === 'active') {
const workflowPhaseDrilldown = (workflowArchiveCompare.phase_changes || []).map((item) => `${item.phase}: ${item.changed ? 'changed' : 'same'}`).join(', ');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['workflow compare left', formatTimestamp(workflowArchiveCompare.left_created_ts || workflowArchiveCompare.left?.created_ts)],
['workflow compare right', formatTimestamp(workflowArchiveCompare.right_created_ts || workflowArchiveCompare.right?.created_ts)],
['phase changes', String((workflowArchiveCompare.phase_changes || []).filter((item) => item.changed).length)],
['artifact delta', String(workflowArchiveCompare.count_delta?.artifact_count ?? 0)],
['ready delta', String(workflowArchiveCompare.count_delta?.ready_for_handoff_count ?? 0)],
['update delta', String(workflowArchiveCompare.count_delta?.needs_update_count ?? 0)],
['pending delta', String(workflowArchiveCompare.count_delta?.pending_capture_count ?? 0)],
['phase drilldown', workflowPhaseDrilldown || 'n/a'],
])
);
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Prefill Compare Replay Note',
onClick: () => prefillOperatorNote(buildWorkflowArchiveCompareReplayNote(workflowArchiveCompare)),
},
{
label: 'Persist Compare Replay Note',
onClick: async () => {
const payload = await persistWorkflowArchiveCompareWritebackServer({
profileKey: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
compare: workflowArchiveCompare,
});
if (!payload || payload.status !== 'saved') {
showErrorPanel('workflow_compare_writeback_failed');
return;
}
await refreshDashboard();
},
},
{
label: 'Export Handoff Starter',
onClick: async () => {
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: Math.max(Number(assistantWorkflowArchiveState.limit || 12), Number(workflowArchiveData?.items?.length || 0)),
left_id: assistantWorkflowArchiveState.selected_left_id,
right_id: assistantWorkflowArchiveState.selected_right_id,
})}`);
downloadJsonFile(exportPayload.export_name || 'workflow-handoff-starter.json', {
export_schema_version: exportPayload.export_schema_version,
handoff_packet_starter: exportPayload.handoff_packet_starter,
handoff_bundle_summary: exportPayload.handoff_bundle_summary,
replay_note_bridge_summary: exportPayload.replay_note_bridge_summary,
});
},
},
{
label: 'Persist Bridge State',
onClick: async () => {
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: Math.max(Number(assistantWorkflowArchiveState.limit || 12), Number(workflowArchiveData?.items?.length || 0)),
left_id: assistantWorkflowArchiveState.selected_left_id,
right_id: assistantWorkflowArchiveState.selected_right_id,
})}`);
const saved = await persistWorkflowArchiveBridgeStateServer({
summary,
exportPayload,
profileKey: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
});
if (!saved) {
showErrorPanel('workflow_bridge_state_persist_failed');
return;
}
await refreshDashboard();
},
},
{
label: 'Export Artifact Bundle',
onClick: async () => {
const exportPayload = await fetchJson(`/trading/workflow-archive/export?${queryString({
instrument_id: Number(instrumentIdInput.value || 1),
profile_key: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
profile_scope: assistantWorkflowArchiveState.profile_scope || 'selected_profile',
query_preset: assistantWorkflowArchiveState.query_preset || '',
current_session: assistantWorkflowArchiveState.current_session || '',
next_phase: assistantWorkflowArchiveState.next_phase || '',
next_artifact_kind: assistantWorkflowArchiveState.next_artifact_kind || '',
query_text: assistantWorkflowArchiveState.query_text || '',
created_after: assistantWorkflowArchiveState.created_after || '',
created_before: assistantWorkflowArchiveState.created_before || '',
limit: Math.max(Number(assistantWorkflowArchiveState.limit || 12), Number(workflowArchiveData?.items?.length || 0)),
left_id: assistantWorkflowArchiveState.selected_left_id,
right_id: assistantWorkflowArchiveState.selected_right_id,
})}`);
downloadJsonFile(exportPayload.export_name || 'workflow-artifact-bundle.json', {
export_schema_version: exportPayload.export_schema_version,
artifact_bundle_summary: exportPayload.artifact_bundle_summary,
structured_export_summary: exportPayload.structured_export_summary,
daily_groups: workflowArchiveData?.daily_groups || [],
session_groups: workflowArchiveData?.session_groups || [],
});
},
},
])
);
const workflowCompareGrid = createElement('div', 'cards assistant-tight-grid');
(workflowArchiveCompare.phase_changes || []).forEach((item) => {
workflowCompareGrid.appendChild(
buildItemCard(
item.phase || 'phase',
item.changed ? 'changed' : 'same',
[
['left body', item.left_body || 'n/a'],
['right body', item.right_body || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(workflowCompareGrid);
}
const workflowGrid = createElement('div', 'cards');
workflowDigest.forEach((item) => {
workflowGrid.appendChild(
buildItemCard(
item.title || item.phase || 'workflow',
item.status || 'n/a',
[
['detail', item.detail || 'n/a'],
['next step', item.next_step || 'n/a'],
['rhythm status', item.rhythm_status || 'n/a'],
['rhythm pending', String(item.rhythm_pending_count ?? 0)],
['next rhythm action', item.next_rhythm_action || 'n/a'],
['session task', item.session_task_label || 'n/a'],
['session task status', item.session_task_status || 'n/a'],
['session task prompt', item.session_task_prompt || 'n/a'],
['checklist', formatList((item.rhythm_checklist || []).map((row) => `${row.label || row.check_id}: ${row.status}`))],
]
)
);
});
decisionAssistantPanel.appendChild(workflowGrid);
const workflowArtifacts = summary.workflow_artifacts || [];
if (workflowArtifacts.length) {
const artifactGrid = createElement('div', 'cards assistant-tight-grid');
workflowArtifacts.forEach((item) => {
artifactGrid.appendChild(
buildItemCard(
item.title || item.phase || 'artifact',
item.artifact_state || 'pending',
[
['kind', item.artifact_kind || 'n/a'],
['session task', item.session_task_label || 'n/a'],
['slot', item.daily_rhythm_slot || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(artifactGrid);
}
if (workflowArchiveData?.items?.length) {
const workflowArchiveGrid = createElement('div', 'cards assistant-tight-grid');
(workflowArchiveData.items || []).forEach((item) => {
const isLeft = String(item.snapshot_id || '') === String(assistantWorkflowArchiveState.selected_left_id || '');
const isRight = String(item.snapshot_id || '') === String(assistantWorkflowArchiveState.selected_right_id || '');
const baselineId = assistantWorkflowArchiveState.pinned_baseline_id || workflowArchiveBaselineSummary?.baseline_snapshot_id;
const isBaseline = String(item.snapshot_id || '') === String(baselineId || '');
const card = buildItemCard(
item.next_artifact_kind || item.next_phase || 'workflow archive',
isBaseline ? 'baseline_pinned' : (isLeft ? 'left_selected' : (isRight ? 'right_selected' : (item.current_session || 'session'))),
[
['snapshot', String(item.snapshot_id ?? 'n/a')],
['profile', item.profile_key || 'n/a'],
['time', formatTimestamp(item.created_ts)],
['focus mode', item.focus_mode || 'n/a'],
['artifacts', String(item.artifact_count ?? 0)],
['ready/update/pending', `${item.ready_for_handoff_count ?? 0} / ${item.needs_update_count ?? 0} / ${item.pending_capture_count ?? 0}`],
['workflow body', item.workflow_body || 'n/a'],
['phase briefs', formatList((item.phase_briefs || []).map((row) => `${row.phase || 'phase'}: ${row.archive_body || row.detail || 'n/a'}`))],
],
[
{
label: isLeft ? 'Left Selected' : 'Select Left',
onClick: () => {
selectAssistantWorkflowArchiveSnapshot('left', item.snapshot_id);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: isRight ? 'Right Selected' : 'Select Right',
onClick: () => {
selectAssistantWorkflowArchiveSnapshot('right', item.snapshot_id);
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Replay Bridge',
onClick: () => {
setWorkflowArchiveBridgeContext(buildWorkflowArchiveBridgeContext(item, 'replay'));
revealAssistantSection('Setup Replay');
},
},
{
label: 'Note Bridge',
onClick: () => {
const context = buildWorkflowArchiveBridgeContext(item, 'note');
setWorkflowArchiveBridgeContext(context);
prefillOperatorNote(buildWorkflowArchiveBridgeNote(item), context);
},
},
{
label: 'Handoff Bridge',
onClick: () => {
setWorkflowArchiveBridgeContext(buildWorkflowArchiveBridgeContext(item, 'handoff'));
revealAssistantSection('Workflow');
},
},
{
label: isBaseline ? 'Baseline Pinned' : 'Pin Baseline',
onClick: () => {
assistantWorkflowArchiveState.pinned_baseline_id = item.snapshot_id;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
{
label: 'Save This Workflow Baseline',
onClick: async () => {
assistantWorkflowArchiveState.pinned_baseline_id = item.snapshot_id;
await persistAssistantArchiveBaselinesServer({
profileKey: assistantWorkflowArchiveState.profile_key || selectedProfileKey,
workflowSnapshotId: item.snapshot_id,
});
await refreshDashboard();
},
},
{
label: 'Compare To Baseline',
onClick: () => {
const pinnedId = assistantWorkflowArchiveState.pinned_baseline_id || workflowArchiveBaselineSummary?.baseline_snapshot_id;
if (!pinnedId || String(pinnedId) === String(item.snapshot_id || '')) return;
assistantWorkflowArchiveState.selected_left_id = item.snapshot_id;
assistantWorkflowArchiveState.selected_right_id = pinnedId;
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
},
]
);
if (isLeft || isRight || isBaseline) card.classList.add('assistant-compare-selected');
workflowArchiveGrid.appendChild(
card
);
});
decisionAssistantPanel.appendChild(workflowArchiveGrid);
}
}
if (opportunities.length) {
appendSectionTitle(decisionAssistantPanel, 'Opportunities');
const opportunityGrid = createElement('div', 'cards');
opportunities.forEach((item) => {
opportunityGrid.appendChild(
buildItemCard(
item.title || 'opportunity',
item.status || 'observe',
[
['kind', item.kind || 'n/a'],
['detail', item.detail || 'n/a'],
['priority', String(item.priority_score ?? 'n/a')],
['reason', item.reason || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(opportunityGrid);
}
[
['review_now', 'Review Now'],
['strong_watch', 'Strong Watch'],
['soft_watch', 'Soft Watch'],
['archive_only', 'Archive Only'],
].forEach(([key, label]) => {
const items = watchlistTiers[key] || [];
if (!items.length) return;
appendSectionTitle(decisionAssistantPanel, `Watchlist: ${label}`);
if (key === 'review_now' && watchlistSummary.focus_matrix) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['watchlist focus', watchlistSummary.focus_matrix.status || 'idle'],
['recommended tier', watchlistSummary.focus_matrix.recommended_tier || 'n/a'],
['recommended session', watchlistSummary.focus_matrix.recommended_session_code || 'n/a'],
['watchlist next prompt', watchlistSummary.next_watchlist_focus_prompt || 'n/a'],
['tier counts', formatJsonInline(watchlistSummary.focus_matrix.tier_counts || {})],
['session counts', formatJsonInline(watchlistSummary.focus_matrix.session_counts || {})],
])
);
}
const tierGrid = createElement('div', 'cards assistant-tight-grid');
items.forEach((item) => {
const card = buildItemCard(
`${label}: ${item.title || 'candidate'}`,
item.status || key,
[
['session', item.session_code || 'n/a'],
['model', item.model_code || 'n/a'],
['quality', String(item.quality_score ?? 'n/a')],
['why this focus', item.trader_focus_reason || item.tier_reason || 'n/a'],
['why no trade', item.trader_no_trade_reason || 'read-only analysis'],
['watch next', item.trader_watch_next || item.suggested_action || 'n/a'],
['missing confirmations', formatList(item.missing_confirmations || [])],
],
item.action_path && item.action_method === 'POST'
? [{
label: 'Run Confirm Check',
onClick: () => runAction(item.action_path, {}),
}]
: []
);
card.classList.add('clickable-card');
if (resolvedFocusCandidate && String(resolvedFocusCandidate.candidate_id || '') === String(item.candidate_id || '')) {
card.classList.add('assistant-focus-card');
}
card.addEventListener('click', () => {
(async () => {
persistAssistantFocusCandidateId(item.candidate_id);
await persistAssistantFocusCandidateServer(item.candidate_id);
await refreshDashboard();
})();
});
tierGrid.appendChild(card);
});
decisionAssistantPanel.appendChild(tierGrid);
});
if (noTradeItems.length) {
appendSectionTitle(decisionAssistantPanel, 'No-Trade Reasons');
const noTradeGrid = createElement('div', 'cards assistant-tight-grid');
noTradeItems.forEach((item) => {
noTradeGrid.appendChild(
buildItemCard(
item.reason || 'no-trade',
item.priority || 'low',
[
['category', item.category || 'n/a'],
['source', item.source || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(noTradeGrid);
}
if (decisionTimeline.length) {
appendSectionTitle(decisionAssistantPanel, 'Timeline');
const timelineGrid = createElement('div', 'cards');
decisionTimeline.forEach((item) => {
timelineGrid.appendChild(
buildItemCard(
item.title || 'timeline',
item.ts || 'n/a',
[
['detail', item.detail || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(timelineGrid);
}
if (explanationDrilldown.length) {
appendSectionTitle(decisionAssistantPanel, 'Explain');
const drilldownGrid = createElement('div', 'cards');
explanationDrilldown.forEach((item) => {
drilldownGrid.appendChild(
buildItemCard(
item.title || 'explanation',
item.status || 'n/a',
[
['detail', item.detail || 'n/a'],
['reasons', formatList(item.reasons || [])],
]
)
);
});
decisionAssistantPanel.appendChild(drilldownGrid);
}
if (reasonCitations.length) {
appendSectionTitle(decisionAssistantPanel, 'Reason Citations');
const citationGrid = createElement('div', 'cards');
reasonCitations.forEach((item) => {
citationGrid.appendChild(
buildItemCard(
item.reason || 'citation',
item.severity || 'supporting',
[
['source', item.source_type || 'n/a'],
['path', item.source_path || 'n/a'],
['detail', item.detail || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(citationGrid);
}
if (learningRollup) {
appendSectionTitle(decisionAssistantPanel, 'Learning');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['learning status', learningRollup.status || 'idle'],
['review entries', String(learningRollup.entry_count ?? 0)],
['pending feedback', String(learningRollup.pending_feedback_count ?? 0)],
['visual mismatches', String(learningRollup.visual_mismatch_count ?? 0)],
['high-value alerts', String(learningRollup.high_value_alert_count ?? 0)],
['quality flags', formatList(learningRollup.quality_flags || [])],
['next review actions', formatList(learningRollup.next_week_actions || [])],
['learning summary', learningRollup.operator_summary || 'n/a'],
])
);
}
if (externalContext) {
appendSectionTitle(decisionAssistantPanel, 'External Context');
decisionAssistantPanel.appendChild(
buildInfoGrid([
['external context', externalContext.status || 'idle'],
['external headline', externalContext.headline || 'n/a'],
['news provider', `${externalContext.provider_name || 'unknown'} / ${externalContext.freshness_code || 'unknown'}`],
['news window', externalContext.news_window_code || 'unknown'],
['active events', formatList(externalContext.active_event_titles || [])],
['macro/news calendar', String(externalContext.macro_news_calendar_count ?? 0)],
['macro/news providers', String(externalContext.macro_news_provider_count ?? 0)],
['provider states', formatJsonInline(externalContext.macro_news_provider_status_counts || {})],
['event window', externalContext.event_window_status || 'n/a'],
['event window prompt', externalContext.event_window_prompt || 'n/a'],
['high volatility window', String(Boolean(externalContext.high_volatility_window))],
['low liquidity window', String(Boolean(externalContext.low_liquidity_window))],
['exchange anomaly window', String(Boolean(externalContext.exchange_anomaly_window))],
['chart sources', String(externalContext.chart_readonly_source_count ?? 0)],
['chart provider registry', String(externalContext.chart_provider_registry_count ?? 0)],
['chart provider states', formatJsonInline(externalContext.chart_provider_registry_status_counts || {})],
['stale chart sources', String(externalContext.chart_stale_source_count ?? 0)],
['chart adapter mode', externalContext.chart_adapter_mode || 'n/a'],
['chart primary mode', externalContext.chart_primary_mode || 'n/a'],
['chart context prompt', externalContext.chart_context_prompt || 'n/a'],
['exchange surfaces', String(externalContext.exchange_context_source_count ?? 0)],
['exchange surface states', formatJsonInline(externalContext.exchange_context_status_counts || {})],
['provider health cards', String(externalContext.provider_health_card_count ?? 0)],
['provider health states', formatJsonInline(externalContext.provider_health_status_counts || {})],
['provider health next', externalContext.provider_health_summary?.next_health_target || 'n/a'],
['provider health prompt', externalContext.provider_health_summary?.next_health_prompt || 'n/a'],
['provider health story', externalContext.provider_health_summary?.health_story || 'n/a'],
['capture surfaces', String(externalContext.capture_surface_card_count ?? 0)],
['capture surface states', formatJsonInline(externalContext.capture_surface_status_counts || {})],
['capture next target', externalContext.capture_surface_summary?.next_capture_target || 'n/a'],
['capture next prompt', externalContext.capture_surface_summary?.next_capture_prompt || 'n/a'],
['capture surface story', externalContext.capture_surface_summary?.capture_story || 'n/a'],
['screenshot readiness', externalContext.screenshot_readiness_summary?.status || 'n/a'],
['screenshot ready', String(externalContext.screenshot_readiness_summary?.screenshot_ready_count ?? 0)],
['autodiscovery needed', String(externalContext.screenshot_readiness_summary?.autodiscovery_needed_count ?? 0)],
['screenshot embed ready', String(externalContext.screenshot_readiness_summary?.embed_ready_count ?? 0)],
['screenshot next target', externalContext.screenshot_readiness_summary?.next_screenshot_target || 'n/a'],
['screenshot next prompt', externalContext.screenshot_readiness_summary?.next_screenshot_prompt || 'n/a'],
['screenshot story', externalContext.screenshot_readiness_summary?.screenshot_story || 'n/a'],
['visual references', String(externalContext.visual_reference_card_count ?? 0)],
['visual prompt', externalContext.visual_reference_next_prompt || 'n/a'],
['visual evidence bridge', externalContext.visual_evidence_bridge_summary?.status || 'n/a'],
['visual bridge target', externalContext.visual_evidence_bridge_summary?.next_bridge_target || 'n/a'],
['visual bridge prompt', externalContext.visual_evidence_bridge_summary?.next_bridge_prompt || 'n/a'],
['visual bridge story', externalContext.visual_evidence_bridge_summary?.bridge_story || 'n/a'],
['surface history', externalContext.surface_selection_history_summary?.status || 'n/a'],
['surface history count', String(externalContext.surface_selection_history_summary?.entry_count ?? 0)],
['latest surface', externalContext.surface_selection_history_summary?.latest_title || 'n/a'],
['latest selection kind', externalContext.surface_selection_history_summary?.latest_selection_kind || 'n/a'],
['surface history recency', externalContext.surface_selection_history_summary?.recency_status || 'n/a'],
['surface history cadence', externalContext.surface_selection_history_summary?.cadence_status || 'n/a'],
['surface cadence story', externalContext.surface_selection_history_summary?.cadence_story || 'n/a'],
['surface revisit needed', String(Boolean(externalContext.surface_selection_history_summary?.revisit_needed))],
['revisit queue count', String(externalContext.surface_selection_history_summary?.revisit_queue_count ?? 0)],
['acknowledged revisits', String(externalContext.surface_selection_history_summary?.acknowledged_count ?? 0)],
['resolution notes', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_count ?? 0)],
['resolution note gaps', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_count ?? 0)],
['note gap queue', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_queue_count ?? 0)],
['note gap oldest', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_oldest_title || 'n/a'],
['note gap avg age', typeof externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_average_age_seconds === 'number' ? `${Math.round(externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_average_age_seconds / 60)}m` : 'n/a'],
['resolution owners', formatJsonInline(externalContext.surface_selection_history_summary?.resolution_filter_summary?.acknowledged_by_counts || {})],
['owner spotlight', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_spotlight?.owner || 'n/a'],
['owner spotlight count', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_spotlight?.count ?? 0)],
['owner cadence', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_cadence_status || 'n/a'],
['owner cadence avg gap', typeof externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_cadence_average_gap_seconds === 'number' ? `${Math.round(externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_cadence_average_gap_seconds / 60)}m` : 'n/a'],
['owner cadence story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_cadence_story || 'n/a'],
['owner trend', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_trend_status || 'n/a'],
['owner trend story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_trend_story || 'n/a'],
['owner handoff', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_handoff_status || 'n/a'],
['owner handoff story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_handoff_story || 'n/a'],
['owner handoff follow-up', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_handoff_follow_up_status || 'n/a'],
['owner handoff follow-up story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_handoff_follow_up_story || 'n/a'],
['resolved owner drift', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_status || 'n/a'],
['resolved owner drift story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_story || 'n/a'],
['resolved owner drift review', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_status || 'n/a'],
['resolved owner drift review story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_story || 'n/a'],
['drift review queue', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_queue_count ?? 0)],
['drift review queue story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_queue_story || 'n/a'],
['drift review queue aging', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_queue_aging_status || 'n/a'],
['drift review queue aging story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.resolved_owner_drift_review_queue_aging_story || 'n/a'],
['active resolution filter', assistantSurfaceResolutionFilter || 'all'],
['cleared queue status', externalContext.surface_selection_history_summary?.cleared_queue_status || 'n/a'],
['cleared queue story', externalContext.surface_selection_history_summary?.cleared_queue_story || 'n/a'],
['resolution history count', String(externalContext.surface_selection_history_summary?.resolution_history_count ?? 0)],
['latest acknowledged by', externalContext.surface_selection_history_summary?.latest_acknowledged_by || 'n/a'],
['latest acknowledged note', externalContext.surface_selection_history_summary?.latest_acknowledged_note || 'n/a'],
['surface revisit prompt', externalContext.surface_selection_history_summary?.revisit_prompt || 'n/a'],
['next revisit prompt', externalContext.surface_selection_history_summary?.next_revisit_prompt || 'n/a'],
['resolution review prompt', externalContext.surface_selection_history_summary?.next_resolution_review_prompt || 'n/a'],
['note gap prompt', externalContext.surface_selection_history_summary?.resolution_filter_summary?.next_note_gap_prompt || 'n/a'],
['owner spotlight prompt', externalContext.surface_selection_history_summary?.resolution_filter_summary?.owner_spotlight_prompt || 'n/a'],
['priority lane status', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_status || 'n/a'],
['priority lane count', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_count ?? 0)],
['priority lane story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_story || 'n/a'],
['priority lane carry-forward', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_carry_forward_status || 'n/a'],
['priority lane carry-forward story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_carry_forward_story || 'n/a'],
['carry-forward aging', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_carry_forward_aging_status || 'n/a'],
['carry-forward aging story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.note_gap_priority_lane_carry_forward_aging_story || 'n/a'],
['follow-up lane status', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_status || 'n/a'],
['follow-up lane count', String(externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_count ?? 0)],
['follow-up lane story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_story || 'n/a'],
['follow-up lane rollover', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_rollover_status || 'n/a'],
['follow-up lane rollover story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_rollover_story || 'n/a'],
['rollover handoff', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_rollover_handoff_status || 'n/a'],
['rollover handoff story', externalContext.surface_selection_history_summary?.resolution_filter_summary?.carry_forward_follow_up_lane_rollover_handoff_story || 'n/a'],
['priority lane prompt', externalContext.surface_selection_history_summary?.resolution_filter_summary?.next_priority_lane_prompt || 'n/a'],
['rollover prompt', externalContext.surface_selection_history_summary?.resolution_filter_summary?.next_follow_up_lane_rollover_prompt || 'n/a'],
['rollover handoff prompt', externalContext.surface_selection_history_summary?.resolution_filter_summary?.next_rollover_handoff_prompt || 'n/a'],
['surface history story', externalContext.surface_selection_history_summary?.provenance_story || 'n/a'],
['dominant surface', externalContext.surface_selection_history_summary?.dominant_surface_title || 'n/a'],
['dominant surface count', String(externalContext.surface_selection_history_summary?.dominant_surface_count ?? 0)],
['dominant source group', externalContext.surface_selection_history_summary?.dominant_source_group || 'n/a'],
['dominant surface story', externalContext.surface_selection_history_summary?.dominant_surface_story || 'n/a'],
['chart stale evidence', formatList((externalContext.chart_stale_source_evidence || []).map((item) => `${item.source_id}: ${item.evidence}`))],
['exchange status', `${externalContext.exchange_status?.provider_name || 'unknown'} / ${externalContext.exchange_status?.status || 'unknown'}`],
['exchange events', formatList(externalContext.exchange_status_titles || [])],
['announcements', `${externalContext.announcements_snapshot?.provider_name || 'unknown'} / ${externalContext.announcements_snapshot?.status || 'unknown'}`],
['announcement titles', formatList(externalContext.announcement_titles || [])],
['waiting items', formatList(externalContext.external_waiting_items || [])],
['council watch items', formatList(externalContext.council_watch_items || [])],
['operator questions', formatList(externalContext.operator_questions || [])],
['next confirmation targets', formatList(externalContext.next_confirmation_targets || [])],
])
);
if (externalContext.visual_evidence_bridge_summary?.next_bridge_url) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Open Visual Bridge',
onClick: () => openTrackedExternalContextLink(externalContext.visual_evidence_bridge_summary?.next_bridge_url, {
surface_id: externalContext.visual_evidence_bridge_summary?.next_bridge_target || 'visual_bridge',
title: externalContext.visual_evidence_bridge_summary?.next_bridge_target || 'visual bridge',
source_group: 'visual_evidence_bridge',
selection_kind: 'bridge_target',
prompt: externalContext.visual_evidence_bridge_summary?.next_bridge_prompt || '',
}),
},
])
);
}
if (externalContext.capture_surface_summary?.next_capture_url) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Open Capture Surface',
onClick: () => openTrackedExternalContextLink(externalContext.capture_surface_summary?.next_capture_url, {
surface_id: externalContext.capture_surface_summary?.next_capture_target || 'capture_surface',
title: externalContext.capture_surface_summary?.next_capture_target || 'capture surface',
source_group: 'capture_surface',
selection_kind: 'capture_target',
prompt: externalContext.capture_surface_summary?.next_capture_prompt || '',
}),
},
])
);
}
if (externalContext.screenshot_readiness_summary?.next_screenshot_url) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Open Screenshot Surface',
onClick: () => openTrackedExternalContextLink(externalContext.screenshot_readiness_summary?.next_screenshot_url, {
surface_id: externalContext.screenshot_readiness_summary?.next_screenshot_target || 'screenshot_surface',
title: externalContext.screenshot_readiness_summary?.next_screenshot_target || 'screenshot surface',
source_group: 'screenshot_surface',
selection_kind: 'screenshot_target',
prompt: externalContext.screenshot_readiness_summary?.next_screenshot_prompt || '',
}),
},
])
);
}
const surfaceHistory = externalContext.surface_selection_history_summary?.items || [];
if (surfaceHistory.length) {
if (externalContext.surface_selection_history_summary?.revisit_target_url) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Reopen Latest Surface',
onClick: () => openTrackedExternalContextLink(
externalContext.surface_selection_history_summary?.revisit_target_url,
{
surface_id: externalContext.surface_selection_history_summary?.revisit_surface_id || 'external_surface',
title: externalContext.surface_selection_history_summary?.revisit_surface_title || 'external surface',
source_group: 'surface_history_revisit',
selection_kind: 'revisit_target',
prompt: externalContext.surface_selection_history_summary?.revisit_prompt || '',
},
),
},
])
);
}
const revisitQueue = externalContext.surface_selection_history_summary?.revisit_queue || [];
if (revisitQueue.length) {
const revisitGrid = createElement('div', 'cards assistant-tight-grid');
revisitQueue.forEach((item) => {
revisitGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'revisit surface',
item.recency_status || 'aging',
[
['group', item.source_group || 'n/a'],
['age', typeof item.age_seconds === 'number' ? `${Math.round(item.age_seconds / 60)}m` : 'n/a'],
['target', item.target_url || 'n/a'],
['selected at', formatTimestamp(item.selected_ts)],
],
item.target_url ? [{
label: 'Reopen Revisit',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'revisit_target',
prompt: externalContext.surface_selection_history_summary?.next_revisit_prompt || '',
}),
}, {
label: 'Acknowledge Revisit',
onClick: async () => {
const payload = await acknowledgeExternalContextSurfaceHistory({
surface_id: item.surface_id || '',
selected_ts: item.selected_ts || '',
});
if (!payload || payload.status !== 'saved') {
showErrorPanel('surface_history_acknowledge_failed');
return;
}
await refreshDashboard();
},
}, {
label: 'Acknowledge With Note',
onClick: async () => {
const note = window.prompt('Resolution note', '');
if (note == null) return;
const payload = await acknowledgeExternalContextSurfaceHistory({
surface_id: item.surface_id || '',
selected_ts: item.selected_ts || '',
note,
});
if (!payload || payload.status !== 'saved') {
showErrorPanel('surface_history_acknowledge_failed');
return;
}
await refreshDashboard();
},
}] : []
)
);
});
decisionAssistantPanel.appendChild(revisitGrid);
}
const historyGrid = createElement('div', 'cards assistant-tight-grid');
surfaceHistory.forEach((item) => {
historyGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'surface history',
item.selection_kind || 'target_url',
[
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['selected at', formatTimestamp(item.selected_ts)],
['prompt', item.prompt || 'n/a'],
],
item.target_url ? [{
label: 'Reopen Surface',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: item.selection_kind || 'target_url',
prompt: item.prompt || '',
}),
}] : []
)
);
});
decisionAssistantPanel.appendChild(historyGrid);
}
const resolutionHistory = externalContext.surface_selection_history_summary?.resolution_history || [];
if (resolutionHistory.length) {
const resolutionFilterSummary = externalContext.surface_selection_history_summary?.resolution_filter_summary || {};
const resolutionFilterOptions = (resolutionFilterSummary.filter_options && resolutionFilterSummary.filter_options.length)
? resolutionFilterSummary.filter_options
: getDefaultSurfaceResolutionFilterOptions(externalContext.surface_selection_history_summary || {});
if (resolutionFilterOptions.length) {
decisionAssistantPanel.appendChild(
buildActionBar(
resolutionFilterOptions.map((item) => ({
label: item.label || item.filter_id || 'resolved',
onClick: () => {
assistantSurfaceResolutionFilter = item.filter_id || 'all';
renderDecisionAssistant(window.__latestDecisionAssistantSummary || summary);
},
}))
)
);
}
const noteGapQueue = resolutionFilterSummary.note_gap_queue || [];
if (noteGapQueue.length) {
const noteGapGrid = createElement('div', 'cards assistant-tight-grid');
noteGapQueue.forEach((item) => {
noteGapGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'note gap surface',
'note_gap',
[
['acknowledged by', item.revisit_acknowledged_by || 'n/a'],
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['acknowledged at', formatTimestamp(item.revisit_acknowledged_ts)],
],
[
item.target_url && {
label: 'Reopen Note Gap',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'note_gap_target',
prompt: resolutionFilterSummary.next_note_gap_prompt || '',
}),
},
{
label: 'Add Resolution Note',
onClick: async () => {
const note = window.prompt('Resolution note', item.revisit_ack_note || '');
if (note == null) return;
const payload = await acknowledgeExternalContextSurfaceHistory({
surface_id: item.surface_id || '',
selected_ts: item.selected_ts || '',
note,
});
if (!payload || payload.status !== 'saved') {
showErrorPanel('surface_history_acknowledge_failed');
return;
}
await refreshDashboard();
},
},
].filter(Boolean)
)
);
});
decisionAssistantPanel.appendChild(noteGapGrid);
}
const priorityLane = resolutionFilterSummary.note_gap_priority_lane_items || [];
if (priorityLane.length) {
const priorityGrid = createElement('div', 'cards assistant-tight-grid');
priorityLane.forEach((item) => {
priorityGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'priority lane',
typeof item.age_seconds === 'number' ? `${Math.round(item.age_seconds / 60)}m` : 'aging',
[
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['selected at', formatTimestamp(item.selected_ts)],
],
[
item.target_url && {
label: 'Open Priority Surface',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'priority_lane_target',
prompt: resolutionFilterSummary.next_priority_lane_prompt || '',
}),
},
].filter(Boolean)
)
);
});
decisionAssistantPanel.appendChild(priorityGrid);
}
const followUpLane = resolutionFilterSummary.carry_forward_follow_up_lane_items || [];
if (followUpLane.length) {
const followUpGrid = createElement('div', 'cards assistant-tight-grid');
followUpLane.forEach((item) => {
followUpGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'follow-up lane',
typeof item.age_seconds === 'number' ? `${Math.round(item.age_seconds / 60)}m` : 'follow_up',
[
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['selected at', formatTimestamp(item.selected_ts)],
],
[
item.target_url && {
label: 'Open Follow-Up Lane',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'follow_up_lane_target',
prompt: resolutionFilterSummary.next_follow_up_lane_prompt || '',
}),
},
item.target_url && {
label: 'Open Rollover Surface',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'follow_up_lane_rollover_target',
prompt: resolutionFilterSummary.next_follow_up_lane_rollover_prompt || '',
}),
},
].filter(Boolean)
)
);
});
decisionAssistantPanel.appendChild(followUpGrid);
}
const driftReviewQueue = resolutionFilterSummary.resolved_owner_drift_review_queue_items || [];
if (driftReviewQueue.length) {
const driftReviewGrid = createElement('div', 'cards assistant-tight-grid');
driftReviewQueue.forEach((item) => {
driftReviewGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'drift review',
'drift_review',
[
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['selected at', formatTimestamp(item.selected_ts)],
],
[
item.target_url && {
label: 'Open Drift Review',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'drift_review_target',
prompt: resolutionFilterSummary.next_follow_up_lane_rollover_prompt || '',
}),
},
item.target_url && {
label: 'Open Rollover Handoff',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'rollover_handoff_target',
prompt: resolutionFilterSummary.next_rollover_handoff_prompt || '',
}),
},
].filter(Boolean)
)
);
});
decisionAssistantPanel.appendChild(driftReviewGrid);
}
const filteredResolutionHistory = resolutionHistory.filter((item) => matchesSurfaceResolutionFilter(item, assistantSurfaceResolutionFilter));
const resolutionGrid = createElement('div', 'cards assistant-tight-grid');
filteredResolutionHistory.forEach((item) => {
resolutionGrid.appendChild(
buildItemCard(
item.title || item.surface_id || 'resolved revisit',
item.revisit_acknowledged_by || 'resolved',
[
['acknowledged at', formatTimestamp(item.revisit_acknowledged_ts)],
['group', item.source_group || 'n/a'],
['target', item.target_url || 'n/a'],
['note', item.revisit_ack_note || 'n/a'],
],
[
item.target_url && {
label: 'Reopen Cleared Surface',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || 'external_surface',
title: item.title || item.surface_id || 'external surface',
source_group: item.source_group || 'external_context',
selection_kind: 'resolved_target',
prompt: externalContext.surface_selection_history_summary?.next_resolution_review_prompt || '',
}),
},
{
label: 'Add Resolution Note',
onClick: async () => {
const note = window.prompt('Resolution note', item.revisit_ack_note || '');
if (note == null) return;
const payload = await acknowledgeExternalContextSurfaceHistory({
surface_id: item.surface_id || '',
selected_ts: item.selected_ts || '',
note,
});
if (!payload || payload.status !== 'saved') {
showErrorPanel('surface_history_acknowledge_failed');
return;
}
await refreshDashboard();
},
},
].filter(Boolean)
)
);
});
decisionAssistantPanel.appendChild(resolutionGrid);
}
const surfaceRankings = externalContext.surface_selection_history_summary?.surface_rankings || [];
const sourceGroupRankings = externalContext.surface_selection_history_summary?.source_group_rankings || [];
if (surfaceRankings.length || sourceGroupRankings.length) {
const groupingGrid = createElement('div', 'cards assistant-tight-grid');
surfaceRankings.slice(0, 3).forEach((item) => {
groupingGrid.appendChild(
buildItemCard(
`Surface ${item.value || 'n/a'}`,
String(item.count ?? 0),
[['count', String(item.count ?? 0)]]
)
);
});
sourceGroupRankings.slice(0, 3).forEach((item) => {
groupingGrid.appendChild(
buildItemCard(
`Group ${item.value || 'n/a'}`,
String(item.count ?? 0),
[['count', String(item.count ?? 0)]]
)
);
});
decisionAssistantPanel.appendChild(groupingGrid);
}
const sourceCards = externalContext.source_cards || [];
if (sourceCards.length) {
const sourceGrid = createElement('div', 'cards');
sourceCards.forEach((item) => {
sourceGrid.appendChild(
buildItemCard(
item.title || item.source_type || 'context source',
item.source_type || 'source',
[
['detail', item.detail || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(sourceGrid);
}
const providerInventory = externalContext.macro_news_provider_inventory || [];
if (providerInventory.length) {
const providerGrid = createElement('div', 'cards assistant-tight-grid');
providerInventory.forEach((item) => {
providerGrid.appendChild(
buildItemCard(
item.provider_name || 'macro provider',
item.status || 'unknown',
[
['freshness', item.freshness_status || 'n/a'],
['surface', item.surface_url || 'n/a'],
['prompt', item.visual_prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(providerGrid);
}
const providerHealthCards = externalContext.provider_health_cards || [];
if (providerHealthCards.length) {
const healthGrid = createElement('div', 'cards assistant-tight-grid');
providerHealthCards.forEach((item) => {
const actions = [];
if (item.target_url) {
actions.push({
label: 'Open Target',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.health_id || item.title || item.provider_name || 'provider_health',
title: item.title || item.provider_name || 'provider health',
source_group: 'provider_health',
selection_kind: 'target_url',
prompt: item.next_visual_prompt || item.health_reason || '',
}),
});
}
if (item.embed_url) {
actions.push({
label: 'Open Embed',
onClick: () => openTrackedExternalContextLink(item.embed_url, {
surface_id: item.health_id || item.title || item.provider_name || 'provider_health_embed',
title: item.title || item.provider_name || 'provider health embed',
source_group: 'provider_health',
selection_kind: 'embed_url',
prompt: item.next_visual_prompt || item.health_reason || '',
}),
});
}
healthGrid.appendChild(
buildItemCard(
item.title || item.provider_name || 'provider health',
item.status || 'monitor',
[
['group', item.surface_group || 'n/a'],
['source status', item.source_status || 'n/a'],
['freshness', item.freshness_status || 'n/a'],
['cache', item.cache_state || 'n/a'],
['capture', String(Boolean(item.capture_supported))],
['embed', item.embed_url ? 'available' : 'n/a'],
['reason', item.health_reason || 'n/a'],
['prompt', item.next_visual_prompt || 'n/a'],
],
actions
)
);
});
decisionAssistantPanel.appendChild(healthGrid);
}
const captureSurfaceCards = externalContext.capture_surface_cards || [];
if (captureSurfaceCards.length) {
const captureGrid = createElement('div', 'cards assistant-tight-grid');
captureSurfaceCards.forEach((item) => {
const actions = [];
if (item.target_url) {
actions.push({
label: 'Open Capture Target',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.surface_id || item.title || item.provider_name || 'capture_surface',
title: item.title || item.provider_name || 'capture surface',
source_group: 'capture_surface_card',
selection_kind: 'target_url',
prompt: item.capture_surface_prompt || '',
}),
});
}
if (item.embed_url) {
actions.push({
label: 'Open Capture Embed',
onClick: () => openTrackedExternalContextLink(item.embed_url, {
surface_id: item.surface_id || item.title || item.provider_name || 'capture_surface_embed',
title: item.title || item.provider_name || 'capture surface embed',
source_group: 'capture_surface_card',
selection_kind: 'embed_url',
prompt: item.capture_surface_prompt || '',
}),
});
}
captureGrid.appendChild(
buildItemCard(
item.title || item.provider_name || 'capture surface',
item.capture_readiness || item.status || 'surface',
[
['group', item.surface_group || 'n/a'],
['capture', String(Boolean(item.capture_supported))],
['screenshot status', item.screenshot_capture_status || 'n/a'],
['embed status', item.screenshot_embed_status || 'n/a'],
['embed', item.embed_ready ? 'ready' : 'n/a'],
['bridge', item.evidence_bridge_status || 'n/a'],
['browser capture', String(Boolean(item.browser_capture_enabled))],
['browser configured', String(Boolean(item.browser_path_configured))],
['screenshot timeout', String(item.screenshot_timeout_seconds ?? 'n/a')],
['viewport', formatJsonInline(item.screenshot_viewport || {})],
['target', item.target_url || 'n/a'],
['embed url', item.embed_url || 'n/a'],
['prompt', item.capture_surface_prompt || 'n/a'],
],
actions
)
);
});
decisionAssistantPanel.appendChild(captureGrid);
}
const calendarEvents = externalContext.macro_news_calendar || [];
if (calendarEvents.length) {
const calendarGrid = createElement('div', 'cards assistant-tight-grid');
calendarEvents.forEach((item) => {
calendarGrid.appendChild(
buildItemCard(
item.title || 'event',
item.window_type || item.source_type || 'window',
[
['source', item.source_type || 'n/a'],
['impact', item.impact || 'n/a'],
['time', formatTimestamp(item.event_ts)],
['detail', item.detail || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(calendarGrid);
}
const chartSources = externalContext.chart_readonly_sources || [];
if (chartSources.length) {
const chartGrid = createElement('div', 'cards assistant-tight-grid');
chartSources.forEach((item) => {
chartGrid.appendChild(
buildItemCard(
item.source_id || 'chart source',
item.status || 'source',
[
['type', item.source_type || 'n/a'],
['freshness', item.freshness_status || 'n/a'],
['status', item.status || 'n/a'],
['stale evidence', item.stale_source_evidence || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(chartGrid);
}
const chartProviderRegistry = externalContext.chart_provider_registry || [];
if (chartProviderRegistry.length) {
const chartProviderGrid = createElement('div', 'cards assistant-tight-grid');
chartProviderRegistry.forEach((item) => {
chartProviderGrid.appendChild(
buildItemCard(
item.provider_name || 'chart provider',
item.status || 'unknown',
[
['symbol', item.symbol || 'n/a'],
['interval', item.interval || 'n/a'],
['freshness', item.freshness_status || 'n/a'],
['target', item.target_url || 'n/a'],
['embed', item.embed_url || 'n/a'],
['capture', String(Boolean(item.capture_supported))],
]
)
);
});
decisionAssistantPanel.appendChild(chartProviderGrid);
}
const exchangeSources = externalContext.exchange_context_sources || [];
if (exchangeSources.length) {
const exchangeGrid = createElement('div', 'cards assistant-tight-grid');
exchangeSources.forEach((item) => {
exchangeGrid.appendChild(
buildItemCard(
item.provider_name || item.surface_type || 'exchange surface',
item.status || 'unknown',
[
['surface', item.surface_type || 'n/a'],
['freshness', item.freshness_status || 'n/a'],
['cache', item.cache_state || 'n/a'],
['target', item.target_url || 'n/a'],
['capture', String(Boolean(item.capture_supported))],
['prompt', item.visual_prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(exchangeGrid);
}
const visualReferences = externalContext.visual_reference_cards || [];
if (visualReferences.length) {
const visualGrid = createElement('div', 'cards assistant-tight-grid');
visualReferences.forEach((item) => {
const actions = [];
if (item.target_url) {
actions.push({
label: 'Open Target',
onClick: () => openTrackedExternalContextLink(item.target_url, {
surface_id: item.visual_id || item.title || item.provider_name || 'visual_reference',
title: item.title || item.provider_name || 'visual reference',
source_group: 'visual_reference_card',
selection_kind: 'target_url',
prompt: item.visual_prompt || '',
}),
});
}
if (item.embed_url) {
actions.push({
label: 'Open Embed',
onClick: () => openTrackedExternalContextLink(item.embed_url, {
surface_id: item.visual_id || item.title || item.provider_name || 'visual_reference_embed',
title: item.title || item.provider_name || 'visual reference embed',
source_group: 'visual_reference_card',
selection_kind: 'embed_url',
prompt: item.visual_prompt || '',
}),
});
}
visualGrid.appendChild(
buildItemCard(
item.title || item.provider_name || 'visual reference',
item.visual_type || item.status || 'visual',
[
['provider', item.provider_name || 'n/a'],
['status', item.status || 'n/a'],
['summary', item.summary || 'n/a'],
['target', item.target_url || 'n/a'],
['embed', item.embed_url || 'n/a'],
['capture', String(Boolean(item.capture_supported))],
['prompt', item.visual_prompt || 'n/a'],
],
actions
)
);
});
decisionAssistantPanel.appendChild(visualGrid);
}
}
if (setupLearningRollup) {
appendSectionTitle(decisionAssistantPanel, 'Setup Replay');
if (workflowArchiveBridgeContext) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['archive replay bridge', workflowArchiveBridgeContext.bridge_mode || 'n/a'],
['archive snapshot', String(workflowArchiveBridgeContext.snapshot_id ?? 'n/a')],
['archive session', workflowArchiveBridgeContext.session_code || 'n/a'],
['archive next phase', workflowArchiveBridgeContext.next_phase || 'n/a'],
['archive artifact', workflowArchiveBridgeContext.next_artifact_kind || 'n/a'],
['archive prompt', workflowArchiveBridgeContext.next_artifact_prompt || 'n/a'],
['archive workflow body', workflowArchiveBridgeContext.workflow_body || 'n/a'],
])
);
}
decisionAssistantPanel.appendChild(
buildInfoGrid([
['setup learning', setupLearningRollup.status || 'idle'],
['setup type', setupLearningRollup.setup_type || 'unknown'],
['setup session', setupLearningRollup.session_code || 'n/a'],
['session source', setupLearningRollup.session_code_source || 'n/a'],
['focus replay scope', setupLearningRollup.focus_replay_scope || 'n/a'],
['focus replay candidate', String(setupLearningRollup.focus_candidate_id ?? 'n/a')],
['focus replay session', setupLearningRollup.focus_session_code || 'n/a'],
['focus replay model', setupLearningRollup.focus_model_code || 'n/a'],
['focus replay prompt', setupLearningRollup.focus_replay_prompt || 'n/a'],
['lesson count', String(setupLearningRollup.lesson_count ?? 0)],
['failure attributions', String(setupLearningRollup.learning_attribution_summary?.failure_reason_count ?? 0)],
['missed opportunities', String(setupLearningRollup.learning_attribution_summary?.missed_opportunity_count ?? 0)],
['learning focus queue', String(setupLearningRollup.learning_focus_queue_count ?? 0)],
['next learning focus', setupLearningRollup.next_learning_focus?.title || 'n/a'],
['next learning prompt', setupLearningRollup.next_learning_focus_prompt || 'n/a'],
['learning focus session', setupLearningRollup.learning_focus_matrix?.recommended_session_code || 'n/a'],
['learning focus state', setupLearningRollup.learning_focus_matrix?.recommended_market_state || 'n/a'],
['learning matrix hint', setupLearningRollup.learning_focus_matrix?.matrix_hint || 'n/a'],
['weekly trend summary', setupLearningRollup.weekly_trend_summary || 'n/a'],
['weekly best session', setupLearningRollup.weekly_trend_breakdown?.best_session || 'n/a'],
['weekly weakest session', setupLearningRollup.weekly_trend_breakdown?.weakest_session || 'n/a'],
['weekly liquid/thin', `${setupLearningRollup.weekly_trend_breakdown?.liquid_session_count ?? 0} / ${setupLearningRollup.weekly_trend_breakdown?.thin_session_count ?? 0}`],
['failure reasons', formatList((setupLearningRollup.failure_reason_attribution || []).map((item) => `${item.reason}: ${item.severity}`))],
['missed opportunity reasons', formatList((setupLearningRollup.missed_opportunity_attribution || []).map((item) => `${item.session_code}: ${item.reason}`))],
['setup/session stats', formatList((setupLearningRollup.setup_session_market_state_stats || []).map((item) => `${item.session_code}/${item.market_state}: ${formatPercent(item.framework_execution_rate)}`))],
['replay samples', String(setupLearningRollup.replay_statistics?.sample_count ?? 0)],
['framework rate', formatPercent(setupLearningRollup.replay_statistics?.framework_execution_rate)],
['model outside rate', formatPercent(setupLearningRollup.replay_statistics?.model_outside_rate)],
['avg R', formatNumber(setupLearningRollup.replay_statistics?.avg_r_multiple, 2)],
['risk violations', String(setupLearningRollup.replay_statistics?.risk_violation_count ?? 0)],
['framework gap vs high', formatPercent(setupLearningRollup.replay_statistics?.comparative_summary?.framework_execution_gap_vs_high)],
['avg R gap vs high', formatNumber(setupLearningRollup.replay_statistics?.comparative_summary?.avg_r_gap_vs_high, 2)],
['framework gap vs low', formatPercent(setupLearningRollup.replay_statistics?.comparative_summary?.framework_execution_gap_vs_low)],
['avg R gap vs low', formatNumber(setupLearningRollup.replay_statistics?.comparative_summary?.avg_r_gap_vs_low, 2)],
['comparison status', setupLearningRollup.replay_statistics?.comparative_summary?.comparison_status || 'n/a'],
['confidence band', setupLearningRollup.replay_statistics?.comparative_summary?.confidence_band || 'n/a'],
['session alignment', setupLearningRollup.replay_statistics?.comparative_summary?.session_alignment || 'n/a'],
['comparison notes', formatList(setupLearningRollup.replay_statistics?.comparative_summary?.notes || [])],
['comparison story', setupLearningRollup.replay_statistics?.comparative_summary?.story || 'n/a'],
['global framework avg', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.framework_execution_global_avg)],
['global avg R', formatNumber(setupLearningRollup.replay_statistics?.broader_baseline_summary?.avg_r_global_avg, 2)],
['global risk avg', formatNumber(setupLearningRollup.replay_statistics?.broader_baseline_summary?.risk_violation_global_avg, 2)],
['framework rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.framework_rank ?? 'n/a')],
['framework percentile', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.framework_percentile)],
['avg R rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.avg_r_rank ?? 'n/a')],
['avg R percentile', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.avg_r_percentile)],
['risk rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.risk_rank ?? 'n/a')],
['risk percentile', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.risk_percentile)],
['composite percentile', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.composite_percentile)],
['risk band', setupLearningRollup.replay_statistics?.broader_baseline_summary?.risk_band || 'n/a'],
['composite band', setupLearningRollup.replay_statistics?.broader_baseline_summary?.composite_band || 'n/a'],
['composite rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.composite_rank ?? 'n/a')],
['position band', setupLearningRollup.replay_statistics?.broader_baseline_summary?.position_band || 'n/a'],
['replay verdict', setupLearningRollup.replay_statistics?.broader_baseline_summary?.replay_verdict || 'n/a'],
['peer summary', setupLearningRollup.replay_statistics?.broader_baseline_summary?.peer_summary || 'n/a'],
['setup family', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family || 'n/a'],
['setup family status', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_status || 'n/a'],
['setup family peers', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_peer_summary || 'n/a'],
['setup family focus', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_focus || 'n/a'],
['family trend status', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.trend_status || 'n/a'],
['family watchlist status', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.watchlist_status || 'n/a'],
['family watchlist priority', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.watchlist_priority || 'n/a'],
['family watchlist score', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.watchlist_priority_score ?? 'n/a')],
['promotion readiness', String(Boolean(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_ready))],
['promotion readiness hint', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_readiness_hint || 'n/a'],
['promotion blockers', formatList(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_blockers || [])],
['promotion queue status', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_queue_status || 'n/a'],
['promotion queue rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_queue_rank ?? 'n/a')],
['promotion next action', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_next_action || 'n/a'],
['promotion decision history', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_decision_history_count ?? 0)],
['promotion decision reasons', formatList((setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_decision_history || []).map((item) => item.reason || item.event))],
['review lane age', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.review_lane_age_status || 'n/a'],
['review lane age score', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.review_lane_age_score ?? 'n/a')],
['review lane aging hint', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.review_lane_aging_hint || 'n/a'],
['review lane SLA status', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.review_lane_sla_status || 'n/a'],
['review lane SLA', formatDurationSeconds(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.review_lane_sla_seconds)],
['promotion backlog priority', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_priority || 'n/a'],
['promotion backlog rank', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_rank ?? 'n/a')],
['promotion backlog reason', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_reason || 'n/a'],
['promotion evidence queue', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_evidence_queue_count ?? 0)],
['promotion evidence', formatList((setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_evidence_queue || []).map((item) => `${item.evidence_type}: ${item.status}`))],
['backlog trend', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_trend_status || 'n/a'],
['backlog handoff', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_trend_handoff || 'n/a'],
['evidence aging', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_evidence_aging_status || 'n/a'],
['evidence aging prompt', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_evidence_aging_prompt || 'n/a'],
['evidence aging queue', formatList((setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_evidence_aging_queue || []).map((item) => `${item.evidence_type}: ${item.aging_status}`))],
['backlog comparison', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_comparison_status || 'n/a'],
['backlog comparison summary', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.promotion_backlog_comparison_summary?.summary || 'n/a'],
['demotion history', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.demotion_history_count ?? 0)],
['demotion reasons', formatList((setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.demotion_history || []).map((item) => item.reason || item.event))],
['family sample threshold', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.sample_threshold ?? 'n/a')],
['family sample gap', String(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.sample_gap ?? 'n/a')],
['family watchlist items', formatList(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.drift_watchlist_items || [])],
['family framework delta', formatPercent(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.framework_delta)],
['family avg R delta', formatNumber(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.avg_r_delta, 2)],
['family risk delta', formatNumber(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.risk_delta, 2)],
['family drift alert', String(Boolean(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.drift_alert))],
['family drift severity', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.drift_severity || 'n/a'],
['family focus recommendation', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.focus_recommendation || 'n/a'],
['family focus reasons', formatList(setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.focus_reasons || [])],
['family trend story', setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_trend_delta?.trend_story || 'n/a'],
['broader story', setupLearningRollup.replay_statistics?.broader_baseline_summary?.story || 'n/a'],
['high-quality session', setupLearningRollup.high_quality_session?.session_code || 'n/a'],
['low-quality session', setupLearningRollup.low_quality_session?.session_code || 'n/a'],
])
);
if (workflowArchiveBridgeContext) {
decisionAssistantPanel.appendChild(
buildActionBar([
{
label: 'Prefill Replay Note',
onClick: () => prefillOperatorNote(buildWorkflowArchiveBridgeNote(workflowArchiveBridgeContext), workflowArchiveBridgeContext),
},
{
label: 'Jump to Review Entry',
onClick: () => revealAssistantSection('Review Entry'),
},
])
);
}
const broadTopSessions = setupLearningRollup.replay_statistics?.broader_baseline_summary?.top_sessions || [];
const broadTopRSessions = setupLearningRollup.replay_statistics?.broader_baseline_summary?.top_r_sessions || [];
const broadTopSafe = setupLearningRollup.replay_statistics?.broader_baseline_summary?.top_safe_sessions || [];
const broadTopComposite = setupLearningRollup.replay_statistics?.broader_baseline_summary?.top_composite_sessions || [];
const peerSessions = setupLearningRollup.replay_statistics?.broader_baseline_summary?.peer_sessions || [];
const setupFamilyPeers = setupLearningRollup.replay_statistics?.broader_baseline_summary?.setup_family_peer_sessions || [];
if (broadTopSessions.length || broadTopRSessions.length || broadTopSafe.length || broadTopComposite.length || peerSessions.length || setupFamilyPeers.length) {
const leaderboardGrid = createElement('div', 'cards assistant-tight-grid');
broadTopSessions.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Top Framework: ${item.session_code || 'session'}`,
formatPercent(item.metric),
[
['samples', String(item.count ?? 0)],
]
)
);
});
broadTopRSessions.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Top Avg R: ${item.session_code || 'session'}`,
formatNumber(item.metric, 2),
[
['samples', String(item.count ?? 0)],
]
)
);
});
broadTopSafe.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Safest: ${item.session_code || 'session'}`,
formatNumber(item.metric, 0),
[
['samples', String(item.count ?? 0)],
]
)
);
});
peerSessions.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Peer ${String(item.relative_position || 'nearby')}: ${item.session_code || 'session'}`,
`rank ${String(item.rank ?? 'n/a')}`,
[
['framework', formatPercent(item.framework_execution_rate)],
['avg R', formatNumber(item.avg_r_multiple, 2)],
['risk violations', String(item.risk_violation_count ?? 0)],
['samples', String(item.count ?? 0)],
]
)
);
});
setupFamilyPeers.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Family Peer: ${item.session_code || 'session'}`,
item.setup_family || 'setup family',
[
['relative', item.relative_position || 'n/a'],
['rank', String(item.rank ?? 'n/a')],
['framework', formatPercent(item.framework_execution_rate)],
['avg R', formatNumber(item.avg_r_multiple, 2)],
['risk violations', String(item.risk_violation_count ?? 0)],
['samples', String(item.count ?? 0)],
]
)
);
});
broadTopComposite.forEach((item) => {
leaderboardGrid.appendChild(
buildItemCard(
`Top Composite: ${item.session_code || 'session'}`,
`${formatPercent(item.framework_execution_rate)} | ${formatNumber(item.avg_r_multiple, 2)}`,
[
['risk violations', String(item.risk_violation_count ?? 0)],
]
)
);
});
decisionAssistantPanel.appendChild(leaderboardGrid);
}
const lessonItems = setupLearningRollup.top_lessons || [];
const learningFocusQueue = setupLearningRollup.learning_focus_queue || [];
if (lessonItems.length) {
const lessonGrid = createElement('div', 'cards');
lessonItems.forEach((item) => {
lessonGrid.appendChild(
buildItemCard(
item.title || 'lesson',
item.lesson_type || 'lesson',
[
['summary', item.summary || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(lessonGrid);
}
if (learningFocusQueue.length) {
const focusGrid = createElement('div', 'cards assistant-tight-grid');
learningFocusQueue.forEach((item) => {
focusGrid.appendChild(
buildItemCard(
item.title || 'learning focus',
item.priority || item.focus_type || 'focus',
[
['type', item.focus_type || 'n/a'],
['session', item.target_session_code || 'n/a'],
['market state', item.target_market_state || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(focusGrid);
}
if (setupLearningRollup.learning_focus_matrix) {
decisionAssistantPanel.appendChild(
buildInfoGrid([
['focus matrix', setupLearningRollup.learning_focus_matrix.status || 'idle'],
['session focus counts', formatJsonInline(setupLearningRollup.learning_focus_matrix.session_focus_counts || {})],
['market-state counts', formatJsonInline(setupLearningRollup.learning_focus_matrix.market_state_focus_counts || {})],
['focus cards', String(setupLearningRollup.learning_focus_matrix.focus_card_count ?? 0)],
])
);
}
}
if (digestHistoryPreview.length) {
const filteredHistory = activeHistoryFilter === 'all'
? digestHistoryPreview
: digestHistoryPreview.filter((item) => String(item.kind || '') === activeHistoryFilter);
const historyGrid = createElement('div', 'cards assistant-history-grid');
filteredHistory.forEach((item) => {
historyGrid.appendChild(
buildItemCard(
item.title || item.kind || 'history',
item.kind || 'history',
[
['detail', item.detail || 'n/a'],
['time', formatTimestamp(item.ts)],
]
)
);
});
decisionAssistantPanel.appendChild(historyGrid);
}
const items = summary.top_priority_items || [];
if (!items.length) {
decisionAssistantPanel.appendChild(createElement('div', 'empty-state', 'No priority items yet. Monitor and wait.'));
} else {
const grid = createElement('div', 'cards');
items.forEach((item) => {
grid.appendChild(
buildItemCard(
item.title || item.kind || 'priority',
item.status || 'observe',
[
['kind', item.kind || 'n/a'],
['detail', item.detail || 'n/a'],
['reason', item.reason || 'n/a'],
]
)
);
});
decisionAssistantPanel.appendChild(grid);
}
if (!evidenceChain.length) {
return;
}
appendSectionTitle(decisionAssistantPanel, 'Evidence');
const evidenceGrid = createElement('div', 'cards');
evidenceChain.forEach((item) => {
evidenceGrid.appendChild(
buildItemCard(
item.title || 'evidence',
item.status || 'n/a',
[
['detail', item.detail || 'n/a'],
['reason', item.reason || 'n/a'],
['focus related', String(Boolean(item.focus_related))],
['focus candidate', String(item.focus_candidate_id ?? 'n/a')],
['evidence keys', formatList(item.evidence_keys || [])],
['missing confirmations', formatList(item.missing_confirmations || [])],
]
)
);
});
decisionAssistantPanel.appendChild(evidenceGrid);
}
function renderMarketState(payload, executions) {
clearNode(marketStatePanel);
const marketState = payload?.market_state || {};
const freshness = marketState.freshness || {};
const session = marketState.session || {};
const newsWindow = marketState.news_window || {};
const riskDecision = payload?.risk_decision || {};
const brokerState = payload?.broker_state || {};
const brokerAccount = brokerState.account || {};
const brokerAlerts = brokerState.alerts || [];
const panel = buildInfoGrid([
['symbol', String(instrumentIdInput.value || '1')],
['session', session.session_code || 'OFF_HOURS'],
['data freshness', freshness.code || 'unknown'],
['news state', newsWindow.code || 'unknown'],
['broker state', brokerState.status || 'unknown'],
['broker equity', formatNumber(brokerAccount.equity, 2)],
['broker available balance', formatNumber(brokerAccount.available_balance, 2)],
['broker open positions', String((brokerState.positions || []).length)],
['broker pending orders', String((brokerState.orders || []).length)],
['broker alerts', formatList(brokerAlerts)],
['account risk state', formatJsonInline(riskDecision.reject_codes || [])],
['open position', String(executions.filter((item) => item.execution_status === 'open').length)],
['kill switch', (riskDecision.reject_codes || []).includes('execution_kill_switch_enabled') ? 'active' : 'off'],
]);
marketStatePanel.appendChild(panel);
}
function renderRuntimeStatus(runtimeStatus, runtimeIncidents, maintenanceSummary) {
clearNode(runtimeStatusPanel);
const tasks = runtimeStatus?.tasks || {};
const blockers = runtimeStatus?.current_blockers || [];
const incidents = runtimeStatus?.incidents || [];
const watchdog = runtimeStatus?.runtime_watchdog || {};
const incidentSummary = runtimeIncidents || runtimeStatus?.incident_summary || {};
const maintenance = maintenanceSummary || {};
const readonlyReliability = maintenance.readonly_live_reliability || {};
const stalledTasks = watchdog?.stalled_tasks || [];
const stalledMap = new Map(stalledTasks.map((item) => [item.name, item]));
runtimeStatusPanel.appendChild(
buildInfoGrid([
['scheduler state', runtimeStatus?.scheduler_state || 'unknown'],
['supervisor state', runtimeStatus?.supervisor_state || 'unknown'],
['enabled', String(Boolean(runtimeStatus?.enabled))],
['degraded', String(Boolean(runtimeStatus?.degraded_mode_state?.is_degraded))],
['symbols', formatList(runtimeStatus?.symbols || [])],
['blockers', formatList(blockers)],
['stalled tasks', formatList(watchdog?.stalled_task_names || [])],
['watchdog checked', formatTimestamp(watchdog?.checked_ts)],
['incident journal', `${incidentSummary.status || 'idle'} | ${incidentSummary.incident_count ?? 0}`],
['incident severity', formatJsonInline(incidentSummary.severity_counts || {})],
['maintenance', `${maintenance.status || 'unavailable'} | blockers ${(maintenance.blockers || []).length}`],
['read-only use today', readonlyReliability.label || 'not checked'],
['last incident', incidents.length ? `${incidents[incidents.length - 1].code} @ ${formatTimestamp(incidents[incidents.length - 1].observed_ts)}` : 'none'],
])
);
const grid = createElement('div', 'cards');
grid.appendChild(
buildItemCard(
'Incident Journal',
incidentSummary.open_incident_count ? 'review' : (incidentSummary.status || 'idle'),
[
['persisted', String(Boolean(incidentSummary.persisted))],
['open / volatile', `${incidentSummary.open_incident_count ?? 0} / ${incidentSummary.volatile_incident_count ?? 0}`],
['sources', formatJsonInline(incidentSummary.source_counts || {})],
['recommended actions', formatList(incidentSummary.recommended_actions || [])],
['latest', incidentSummary.latest_incident ? `${incidentSummary.latest_incident.severity || 'unknown'} ${incidentSummary.latest_incident.reason || 'runtime_incident'}` : 'none'],
]
)
);
grid.appendChild(
buildItemCard(
'Read-Only Live Reliability',
readonlyReliability.label || 'not checked',
[
['trader conclusion', readonlyReliability.conclusion || 'not checked'],
['proxy', formatBacktestDecision(readonlyReliability.proxy_status || 'unknown')],
['market freshness', formatBacktestDecision(readonlyReliability.market_freshness || 'unknown')],
['runtime', formatBacktestDecision(readonlyReliability.runtime_status || 'unknown')],
['review packet', formatBacktestDecision(readonlyReliability.review_packet_status || 'unknown')],
['REST fallback', formatBacktestDecision(readonlyReliability.rest_fallback || 'unknown')],
['stream status', formatBacktestDecision(readonlyReliability.stream_status || 'unknown')],
['news / account warnings', formatList(readonlyReliability.news_account_warnings || [])],
['boundary', readonlyReliability.execution_boundary || 'read_only_analysis_no_order_submission'],
]
)
);
grid.appendChild(
buildItemCard(
'Maintenance Rollup',
maintenance.status || 'unavailable',
[
['blockers', formatList(maintenance.blockers || [])],
['warnings', formatList(maintenance.warnings || [])],
['automatic actions', formatList((maintenance.maintenance_actions || {}).automatic_actions || [])],
['operator actions', formatList((maintenance.maintenance_actions || {}).operator_actions || [])],
['p23 assertions', formatJsonInline(maintenance.p23_assertions || {})],
]
)
);
Object.entries(tasks).forEach(([name, task]) => {
const stalled = stalledMap.get(name) || null;
grid.appendChild(
buildItemCard(
name,
stalled ? 'warning' : (task.last_status || 'idle'),
[
['last success', formatTimestamp(task.last_success_ts)],
['next run', formatTimestamp(task.next_run_ts)],
['run count', String(task.run_count ?? 0)],
['success / failure', `${task.success_count ?? 0} / ${task.failure_count ?? 0}`],
['stalled', stalled ? `${stalled.reason} (${formatNumber(stalled.age_seconds, 1)}s > ${stalled.threshold_seconds}s)` : 'no'],
['last error', task.last_error || 'none'],
['details', formatJsonInline(task.details || {})],
]
)
);
});
runtimeStatusPanel.appendChild(grid);
}
function renderDecisionPacket(packet, alertRows) {
clearNode(decisionPacketPanel);
if (!packet || packet.status === 'unavailable') {
decisionPacketPanel.appendChild(createElement('div', 'empty-state', 'Decision packet unavailable.'));
return;
}
decisionPacketPanel.appendChild(
buildInfoGrid([
['status', packet.status || 'unknown'],
['recommendation', packet.action_recommendation || 'monitor'],
['operator mode', packet.operator_mode || 'unknown'],
['trust classification', packet.trust_classification || 'unknown'],
['bias', packet.bias || 'unknown'],
['setup', packet.setup_type || 'n/a'],
['candidate', packet.candidate_id || 'n/a'],
['ticket', packet.execution_ticket_id || 'n/a'],
['risk result', formatJsonInline(packet.risk_result?.reasons || [])],
['why allowed', formatList(packet.why_allowed || [])],
['why blocked', formatList(packet.why_blocked || [])],
['ai explanation', packet.ai_explanation || 'n/a'],
['council summary', packet.research_council?.research_summary || 'n/a'],
['council confidence', packet.research_council?.committee_confidence != null ? formatNumber(packet.research_council.committee_confidence, 2) : 'n/a'],
['council follow-up', formatList(packet.research_council?.follow_up_checks || [])],
['council watch', formatList(packet.research_council?.recommended_watch_items || [])],
])
);
const grid = createElement('div', 'cards');
grid.appendChild(
buildItemCard(
'Plan Context',
packet.action_recommendation || 'monitor',
[
['narrative', packet.narrative || 'n/a'],
['primary draw', formatJsonInline(packet.primary_draw || {})],
['confirmation', formatJsonInline(packet.confirmation_chain || {})],
['entry zone', `${formatNumber(packet.entry_zone?.low, 3)} - ${formatNumber(packet.entry_zone?.high, 3)}`],
['stop', formatNumber(packet.stop_loss, 3)],
['targets', formatJsonInline(packet.targets || {})],
['invalidation', formatJsonInline(packet.invalidation || {})],
['expiry', formatTimestamp(packet.expiry_ts)],
]
)
);
const recentAlerts = alertRows?.items || packet.alerts || [];
recentAlerts.slice(0, 3).forEach((alert) => {
grid.appendChild(
buildItemCard(
alert.alert_type || 'alert',
alert.status || 'queued',
[
['channel', alert.channel || 'workbench'],
['message', alert.message || 'n/a'],
['payload', formatJsonInline(alert.payload || {})],
]
)
);
});
decisionPacketPanel.appendChild(grid);
}
function renderTrustScore(payload) {
clearNode(trustScorePanel);
const trustClass = trustClassFilterInput.value || 'all';
const models = (payload?.models || []).filter((model) => trustClass === 'all' || model.classification === trustClass);
trustScorePanel.appendChild(
buildInfoGrid([
['whitelist', formatList(payload?.whitelist || [])],
['observe', formatList(payload?.observe_list || [])],
['blacklist', formatList(payload?.blacklist || [])],
['next actions', formatList(payload?.next_actions || [])],
])
);
if (!models.length) {
trustScorePanel.appendChild(createElement('div', 'empty-state', 'No trust-score samples yet.'));
return;
}
const grid = createElement('div', 'cards');
models.forEach((model) => {
grid.appendChild(
buildItemCard(
model.model_code || 'model',
model.classification || 'observe',
[
['score', formatNumber(model.score, 1)],
['recommendation', model.recommendation || 'observe_only'],
['operator mode', model.operator_mode || 'unknown'],
['sample size', String(model.sample_size ?? 0)],
['real trades', String(model.real_trade_count ?? 0)],
['framework rate', formatPercent(model.framework_execution_rate)],
['out-of-model rate', formatPercent(model.out_of_model_trade_rate)],
['risk violation rate', formatPercent(model.risk_violation_rate)],
['expectancy R', formatNumber(model.expectancy_r, 2)],
['quality gate', String(Boolean(model.quality_gate_passed))],
['reasons', formatList(model.reasons || [])],
],
[],
formatJsonInline(model.session_recommendations || [])
)
);
});
trustScorePanel.appendChild(grid);
}
function renderStrategyBacktests(payload) {
if (!strategyBacktestPanel) return;
clearNode(strategyBacktestPanel);
if (payload?.unavailable) {
strategyBacktestPanel.appendChild(createElement('div', 'empty-state error-state', 'Strategy backtest data unavailable.'));
return;
}
const latest = payload?.latest || (payload?.items || [])[0] || null;
if (!latest) {
strategyBacktestPanel.appendChild(createElement('div', 'empty-state', 'No stored backtest runs yet.'));
strategyBacktestPanel.appendChild(
buildInfoGrid([
['Next Action', 'Run replay no-lookahead backtest'],
['Boundary', 'Read-only analysis; no order submission'],
])
);
return;
}
const summary = latest.summary || {};
const qualityGate = payload?.quality_gate || summary.quality_gate || {};
const passed = Boolean(qualityGate.passed);
const operatorSummary = payload?.operator_summary || {};
const doctrineCohort = latest.doctrine_backtest_cohort || summary.doctrine_backtest_cohort || {};
const doctrinePromotionGate = doctrineCohort.promotion_gate || {};
const liquidityStatus =
latest.liquidity_kernel_status ||
summary.liquidity_kernel_status ||
doctrineCohort.liquidity_kernel_status ||
{};
const liquidityFeatures =
latest.liquidity_backtest_features ||
summary.liquidity_backtest_features ||
doctrineCohort.liquidity_backtest_features ||
liquidityStatus.features ||
{};
strategyBacktestPanel.appendChild(
buildInfoGrid([
['Latest Backtest', `#${latest.id ?? 'n/a'} ${latest.model_code || ''}`.trim()],
['Quality Gate', passed ? 'Passed' : 'Blocked'],
['Decision', formatBacktestDecision(operatorSummary.decision)],
['Reason', formatBacktestDecision(operatorSummary.reason)],
['Setup Playbook', doctrineCohort.setup_playbook_id || 'missing_playbook'],
['Doctrine Cohort', doctrineCohort.cohort_key || 'missing_playbook::incomplete'],
['Doctrine Completeness', doctrineCohort.doctrine_completeness || 'incomplete'],
['Liquidity Kernel', formatBacktestDecision(liquidityStatus.status || 'study_only')],
['Liquidity Reason', formatBacktestDecision(liquidityStatus.reason || 'missing_liquidity_target')],
['Liquidity Target', liquidityFeatures.liquidity_target_side || 'missing_liquidity_target'],
['Liquidity Pool', liquidityFeatures.liquidity_pool_id || 'missing_liquidity_pool'],
['Promotion Gate', doctrinePromotionGate.passed ? 'Passed' : 'Blocked'],
['Instrument ID', latest.instrument_id ?? 'n/a'],
['Timeframe', formatJsonInline(latest.timeframe_set || {})],
['Started', formatTimestamp(latest.started_ts)],
['Ended', formatTimestamp(latest.ended_ts)],
['Mode', latest.config?.mode || latest.config?.backtest_mode || 'replay_no_lookahead'],
])
);
const cards = createElement('div', 'cards');
cards.appendChild(
buildMetricCard('Sample Count', String(summary.total_signals ?? summary.candidate_count ?? 0), 'total replay samples')
);
cards.appendChild(
buildMetricCard('Executed Samples', String(summary.executed_signals ?? 0), `executed rate ${formatPercent(summary.executed_rate)}`)
);
cards.appendChild(
buildMetricCard('Total R', formatNumber(summary.total_r, 2), `expectancy ${formatNumber(summary.expectancy_r, 2)} R`)
);
cards.appendChild(
buildMetricCard('Profit Factor', formatNumber(summary.profit_factor_r, 2), `win rate ${formatPercent(summary.win_rate)}`)
);
cards.appendChild(
buildMetricCard('Max Drawdown R', formatNumber(summary.max_drawdown_r, 2), `loss streak ${summary.max_consecutive_losses ?? 0}`)
);
cards.appendChild(
buildMetricCard('Quality Gate', passed ? 'Passed' : 'Blocked', formatList((qualityGate.reasons || []).map(formatBacktestDecision), 'No gate blockers'))
);
cards.appendChild(
buildMetricCard(
'Liquidity Kernel',
liquidityStatus.passed ? 'Mapped' : 'Blocked',
formatList((liquidityStatus.reasons || []).map(formatBacktestDecision), 'Liquidity chain mapped')
)
);
strategyBacktestPanel.appendChild(cards);
strategyBacktestPanel.appendChild(buildBacktestCurve(summary.cumulative_r_curve || []));
const detailGrid = createElement('div', 'cards compact-cards');
detailGrid.appendChild(
buildItemCard(
'Top Sessions',
'review',
topBacktestBuckets(summary.session_performance || summary.by_session || {}).map((item) => [
item.key,
`${formatNumber(item.expectancy_r, 2)} R / ${formatPercent(item.win_rate)} / ${item.count ?? 0} samples`,
])
)
);
detailGrid.appendChild(
buildItemCard(
'Failure Reasons',
'review',
topCountEntries(summary.failure_reasons || {}).map((item) => [formatBacktestDecision(item.key), String(item.value)])
)
);
detailGrid.appendChild(
buildItemCard(
'Doctrine Cohorts',
`${payload?.doctrine_cohort_summary?.cohort_count ?? 0} cohorts`,
(payload?.doctrine_cohort_summary?.cohorts || []).slice(0, 5).map((item) => [
item.cohort_key || 'missing_playbook::incomplete',
`${item.run_count ?? 0} runs / ${item.quality_gate_passed_count ?? 0} passed / ${item.promotable_count ?? 0} promotable`,
])
)
);
detailGrid.appendChild(
buildItemCard(
'Liquidity Kernel',
`${payload?.liquidity_kernel_summary?.passed_count ?? 0} mapped / ${payload?.liquidity_kernel_summary?.blocked_count ?? 0} blocked`,
topCountEntries(payload?.liquidity_kernel_summary?.reason_counts || summary.liquidity_kernel_reason_counts || {})
.slice(0, 5)
.map((item) => [formatBacktestDecision(item.key), String(item.value)])
)
);
detailGrid.appendChild(
buildItemCard(
'Recent Backtest Runs',
`${payload?.item_count ?? (payload?.items || []).length} runs`,
(payload?.items || []).slice(0, 5).map((item) => [
`#${item.id}`,
`${item.doctrine_backtest_cohort?.cohort_key || item.model_code || 'model'} / ${formatTimestamp(item.started_ts)} / ${item.summary?.quality_gate?.passed ? 'Passed' : 'Blocked'}`,
])
)
);
strategyBacktestPanel.appendChild(detailGrid);
}
function buildBacktestCurve(curve) {
const panel = createElement('div', 'backtest-curve-panel');
panel.appendChild(createElement('div', 'assistant-section-title', 'Equity Curve'));
if (!Array.isArray(curve) || !curve.length) {
panel.appendChild(createElement('div', 'empty-state', 'No equity curve points recorded.'));
return panel;
}
const numbers = curve.map((value) => Number(value)).filter((value) => Number.isFinite(value));
if (!numbers.length) {
panel.appendChild(createElement('div', 'empty-state', 'No equity curve points recorded.'));
return panel;
}
const min = Math.min(...numbers);
const max = Math.max(...numbers);
const range = Math.max(1, max - min);
const chart = createElement('div', 'backtest-curve');
numbers.slice(-80).forEach((value) => {
const bar = createElement('span', `backtest-curve-bar${value < 0 ? ' is-negative' : ''}`);
bar.style.height = `${16 + ((value - min) / range) * 64}px`;
bar.title = `${formatNumber(value, 2)} R`;
chart.appendChild(bar);
});
panel.appendChild(chart);
panel.appendChild(
buildInfoGrid([
['Curve Points', String(numbers.length)],
['Last Total R', formatNumber(numbers[numbers.length - 1], 2)],
['Best Total R', formatNumber(max, 2)],
['Worst Total R', formatNumber(min, 2)],
])
);
return panel;
}
function topBacktestBuckets(bucketMap) {
return Object.entries(bucketMap || {})
.map(([key, value]) => ({ key, ...(value || {}) }))
.sort((left, right) => Number(right.expectancy_r || 0) - Number(left.expectancy_r || 0))
.slice(0, 5);
}
function topCountEntries(countMap) {
return Object.entries(countMap || {})
.map(([key, value]) => ({ key, value: Number(value || 0) }))
.sort((left, right) => right.value - left.value)
.slice(0, 5);
}
function formatBacktestDecision(value) {
const text = String(value || 'n/a').replace(/_/g, ' ');
return text.replace(/\b\w/g, (letter) => letter.toUpperCase());
}
function renderLiveReadiness(payload) {
clearNode(liveReadinessPanel);
const okxSandboxPreflight = payload?.okx_sandbox_preflight_summary || null;
liveReadinessPanel.appendChild(
buildInfoGrid([
['ready for real live', String(Boolean(payload?.ready_for_real_live))],
['blocking reasons', formatList(payload?.blocking_reasons || [])],
['protocol version', payload?.operator_confirmation_protocol?.protocol_version || 'n/a'],
['latest live audits', String((payload?.recent_live_audits || []).length)],
['latest ticket', payload?.latest_ticket?.id || 'n/a'],
])
);
if (okxSandboxPreflight) {
liveReadinessPanel.appendChild(
buildInfoGrid([
['okx sandbox preflight', okxSandboxPreflight.status || 'n/a'],
['sandbox next gate', okxSandboxPreflight.next_gate || 'n/a'],
['simulated trading header', formatJsonInline(okxSandboxPreflight.sandbox_header || {})],
['sandbox credentials', String(Boolean(okxSandboxPreflight.sandbox_credentials_present))],
['submit dry-run', String(Boolean(okxSandboxPreflight.submit_dry_run_ready))],
['cancel dry-run', String(Boolean(okxSandboxPreflight.cancel_dry_run_ready))],
['query order dry-run', String(Boolean(okxSandboxPreflight.query_order_dry_run_ready))],
['query fills dry-run', String(Boolean(okxSandboxPreflight.query_fills_dry_run_ready))],
['idempotency key', okxSandboxPreflight.idempotency_key_preview || 'n/a'],
['error normalization', formatList(Object.keys(okxSandboxPreflight.error_normalization || {}))],
['real live after sandbox', okxSandboxPreflight.execution_boundary || 'real_live_still_blocked'],
['sandbox summary', okxSandboxPreflight.operator_summary || 'n/a'],
])
);
}
const grid = createElement('div', 'cards');
(payload?.checklist || []).forEach((item) => {
grid.appendChild(
buildItemCard(
item.code || 'check',
item.passed ? 'passed' : 'blocked',
[
['passed', String(Boolean(item.passed))],
['detail', item.detail || 'n/a'],
]
)
);
});
if ((payload?.checklist || []).length) {
liveReadinessPanel.appendChild(grid);
}
}
function renderLaunchReadiness(payload) {
clearNode(launchReadinessPanel);
const liveAnalysisAssistantSummary = payload?.live_analysis_assistant_summary || null;
const readonlyLiveHealthSummary = payload?.readonly_live_health_summary || liveAnalysisAssistantSummary?.health_summary || null;
launchReadinessPanel.appendChild(
buildInfoGrid([
['live analysis assistant ready', String(Boolean(payload?.live_analysis_assistant_ready))],
['analysis only ready', String(Boolean(payload?.analysis_only_ready))],
['restricted decision support ready', String(Boolean(payload?.restricted_decision_support_ready))],
['decision support ready', String(Boolean(payload?.decision_support_ready))],
['execution assist ready', String(Boolean(payload?.execution_assist_ready))],
['real trade loop ready', String(Boolean(payload?.real_trade_loop_ready))],
['assisted trading ready', String(Boolean(payload?.assisted_trading_ready))],
['real live ready', String(Boolean(payload?.real_live_ready))],
['product mode', payload?.product_operating_mode || 'unknown'],
['product capabilities', formatJsonInline(payload?.product_capabilities || {})],
['boundary notes', formatList(payload?.product_boundary_notes || [])],
['blocking reasons', formatList(payload?.blocking_reasons || [])],
['warning reasons', formatList(payload?.warning_reasons || [])],
['next actions', formatList(payload?.next_actions || [])],
])
);
if (liveAnalysisAssistantSummary) {
launchReadinessPanel.appendChild(
buildInfoGrid([
['Read-only Live Analysis', liveAnalysisAssistantSummary.status || 'n/a'],
['ready_for_readonly_live_analysis', String(Boolean(liveAnalysisAssistantSummary.ready_for_readonly_live_analysis))],
['must_not_trade', String(Boolean(liveAnalysisAssistantSummary.must_not_trade))],
['No order submission', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.no_order_submission))],
['Not a buy/sell instruction', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.not_buy_sell_instruction))],
['Execution remains disabled', String(Boolean(liveAnalysisAssistantSummary.launch_boundary?.execution_remains_disabled))],
['api health', readonlyLiveHealthSummary?.api_health || 'n/a'],
['runtime health', readonlyLiveHealthSummary?.runtime_health || 'n/a'],
['market freshness', readonlyLiveHealthSummary?.market_freshness || 'n/a'],
['market stream', readonlyLiveHealthSummary?.market_stream || 'n/a'],
['broker/account context', readonlyLiveHealthSummary?.broker_account_context || 'n/a'],
['latest decision packet timestamp', formatTimestamp(readonlyLiveHealthSummary?.latest_decision_packet_timestamp)],
['latest review packet timestamp', formatTimestamp(readonlyLiveHealthSummary?.latest_review_packet_timestamp)],
['current candidate count', String(readonlyLiveHealthSummary?.current_candidate_count ?? 0)],
['current blocker', readonlyLiveHealthSummary?.current_blocker || 'none'],
['read-only recommendation', readonlyLiveHealthSummary?.recommendation || 'n/a'],
['allowed actions', formatList(liveAnalysisAssistantSummary.allowed_actions || [])],
['blocked actions', formatList(liveAnalysisAssistantSummary.blocked_actions || [])],
])
);
}
if (payload?.decision_support_boundary_summary) {
const boundary = payload.decision_support_boundary_summary;
launchReadinessPanel.appendChild(
buildInfoGrid([
['operator boundary', boundary.label || 'n/a'],
['boundary summary', boundary.operator_summary || 'n/a'],
['current model boundary', boundary.current_model_boundary || 'n/a'],
['current model reason', boundary.current_model_reason || 'n/a'],
['live execution boundary', boundary.live_execution_boundary || 'n/a'],
['live execution reason', boundary.live_execution_reason || 'n/a'],
['allowed operator actions', formatList(boundary.allowed_operator_actions || [])],
['blocked operator actions', formatList(boundary.blocked_operator_actions || [])],
['boundary next gate', boundary.next_boundary_gate || 'n/a'],
['boundary gate reason', boundary.next_boundary_gate_reason || 'n/a'],
])
);
}
if (payload?.decision_support_promotion_summary) {
const promotion = payload.decision_support_promotion_summary;
launchReadinessPanel.appendChild(
buildInfoGrid([
['decision support promotion', promotion.status || 'n/a'],
['strict decision support ready', String(Boolean(promotion.strict_decision_support_ready))],
['current decision support ready', String(Boolean(promotion.current_decision_support_ready))],
['execution after promotion', promotion.execution_boundary_after_promotion || 'n/a'],
['real live after promotion', promotion.real_live_boundary_after_promotion || 'n/a'],
['promotion model', promotion.candidate_model_code || 'n/a'],
['promotion classification', promotion.candidate_classification || 'n/a'],
['operator feedback samples', String(promotion.operator_review_sample_count ?? 0)],
['promotion criteria', `${promotion.passed_criteria_count ?? 0}/${promotion.required_criteria_count ?? 0}`],
['failed promotion criteria', formatList(promotion.failed_criteria || [])],
['next promotion gate', promotion.next_promotion_gate || 'n/a'],
['promotion summary', promotion.operator_summary || 'n/a'],
])
);
}
if (payload?.shadow_paper_validation_summary) {
const shadowPaper = payload.shadow_paper_validation_summary;
launchReadinessPanel.appendChild(
buildActionBar([
{ label: 'Record Shadow Observation', onClick: () => recordShadowPaperObservation('pending') },
{ label: 'Agree Shadow Observation', onClick: () => recordShadowPaperObservation('agree') },
{ label: 'Disagree Shadow Observation', onClick: () => recordShadowPaperObservation('disagree') },
])
);
launchReadinessPanel.appendChild(
buildInfoGrid([
['shadow paper validation', shadowPaper.status || 'n/a'],
['shadow validation status', shadowPaper.status || 'n/a'],
['shadow observed days', `${shadowPaper.observed_shadow_day_count ?? 0}/${shadowPaper.window_days ?? 0}`],
['shadow observation samples', String(shadowPaper.shadow_observation_count ?? 0)],
['shadow observation days', String(shadowPaper.shadow_observation_day_count ?? 0)],
['shadow candidates', String(shadowPaper.candidate_count ?? 0)],
['paper ticket samples', String(shadowPaper.paper_ticket_count ?? 0)],
['paper execution samples', String(shadowPaper.paper_execution_count ?? 0)],
['operator feedback samples', String(shadowPaper.operator_feedback_count ?? 0)],
['operator observation feedback', String(shadowPaper.operator_observation_feedback_count ?? 0)],
['journal samples', String(shadowPaper.journal_entry_count ?? 0)],
['shadow criteria', `${shadowPaper.passed_criteria_count ?? 0}/${shadowPaper.required_criteria_count ?? 0}`],
['failed shadow criteria', formatList(shadowPaper.failed_criteria || [])],
['next shadow gate', shadowPaper.next_validation_gate || 'n/a'],
['sample collection next actions', formatList(shadowPaper.sample_collection_plan?.next_actions || [])],
['real live after shadow', shadowPaper.execution_boundary || 'real_live_still_blocked'],
['shadow validation summary', shadowPaper.operator_summary || 'n/a'],
['shadow daily coverage', formatList((shadowPaper.daily_coverage || []).slice(-5).map((item) => `${item.date}: o${item.shadow_observation_count}/c${item.candidate_count}/p${item.paper_execution_count}/f${item.operator_feedback_count}`))],
])
);
}
const grid = createElement('div', 'cards');
(payload?.checklist || []).forEach((item) => {
grid.appendChild(
buildItemCard(
item.code || 'check',
item.passed ? 'passed' : item.severity || 'warning',
[
['passed', String(Boolean(item.passed))],
['severity', item.severity || 'n/a'],
['detail', item.detail || 'n/a'],
]
)
);
});
if ((payload?.checklist || []).length) {
launchReadinessPanel.appendChild(grid);
}
}
function renderSessionFocus(payload) {
clearNode(sessionFocusPanel);
const items = payload?.items || [];
const filtered = filterBySession(items, (item) => item.session_code);
if (!filtered.length) {
sessionFocusPanel.appendChild(createElement('div', 'empty-state', 'No session focus rows available.'));
return;
}
const grid = createElement('div', 'cards');
filtered.forEach((item) => {
const recommendation = item.session_recommendation || {};
grid.appendChild(
buildItemCard(
item.session_code || 'session',
recommendation.classification || item.status || 'observe',
[
['status', item.status || 'unknown'],
['window', `${formatTimestamp(item.start_ts)} -> ${formatTimestamp(item.end_ts)}`],
['candidates', String(item.candidate_count ?? 0)],
['executable', String(item.executable_candidate_count ?? 0)],
['open executions', String(item.open_execution_count ?? 0)],
['alerts', String(item.alert_count ?? 0)],
['recommendation', `${recommendation.classification || 'observe'} @ ${formatNumber(recommendation.score, 1)}`],
['action hint', item.action_hint || 'observe'],
]
)
);
});
sessionFocusPanel.appendChild(grid);
}
function renderAlertHistory(alertRows) {
clearNode(alertHistoryPanel);
const items = filterBySession(alertRows?.items || [], (item) => (item.payload || {}).session_code);
if (!items.length) {
alertHistoryPanel.appendChild(createElement('div', 'empty-state', 'No alert history for current filters.'));
return;
}
const grid = createElement('div', 'cards');
items.slice(0, 8).forEach((alert) => {
grid.appendChild(
buildItemCard(
alert.alert_type || 'alert',
alert.status || 'queued',
[
['message', alert.message || 'n/a'],
['created', formatTimestamp(alert.created_ts)],
['channel', alert.channel || 'workbench'],
['payload', formatJsonInline(alert.payload || {})],
]
)
);
});
alertHistoryPanel.appendChild(grid);
}
function renderAlertQuality(summary, operatorDigest) {
clearNode(alertQualityPanel);
const delivery = summary?.delivery_summary || {};
const alertFeedback = summary?.alert_feedback_summary || {};
const visualFeedback = summary?.visual_feedback_summary || {};
const reviewSummary = summary?.visual_review_summary || {};
const silentWindow = summary?.silent_window || {};
const digestCounts = operatorDigest?.summary_counts || {};
const reviewQueue = operatorDigest?.review_queue || [];
alertQualityPanel.appendChild(
buildInfoGrid([
['recent alerts', String(summary?.recent_alert_count ?? 0)],
['recent visual reviews', String(summary?.recent_visual_review_count ?? 0)],
['silent window', `${silentWindow.active ? 'active' : 'inactive'} | ${silentWindow.window_label || 'n/a'}`],
['operator digest', `${operatorDigest?.status || 'idle'} | queue ${reviewQueue.length}`],
['delivery success', formatPercent(delivery.success_rate)],
['alert usefulness', formatPercent(alertFeedback.positive_rate)],
['visual helpfulness', formatPercent(visualFeedback.positive_rate)],
['quality flags', formatList(summary?.quality_flags || [])],
['operator summary', summary?.operator_summary || 'n/a'],
])
);
const grid = createElement('div', 'cards');
grid.appendChild(
buildItemCard(
'Operator Digest',
reviewQueue.length ? 'review' : (operatorDigest?.status || 'idle'),
[
['high value alerts', String(digestCounts.high_value_alert_count ?? 0)],
['suppressed / failed-retry', `${digestCounts.suppressed_delivery_count ?? 0} / ${digestCounts.failed_or_retry_delivery_count ?? 0}`],
['visual mismatches', String(digestCounts.visual_mismatch_count ?? 0)],
['pending feedback', String(digestCounts.pending_feedback_count ?? 0)],
['review queue', formatList(reviewQueue.slice(0, 4).map((item) => `${item.priority || 'n/a'}:${item.queue_type || 'item'}`))],
['digest summary', operatorDigest?.operator_summary || 'n/a'],
]
)
);
grid.appendChild(
buildItemCard(
'Delivery',
delivery.failed_count ? 'warning' : 'ok',
[
['attempts', String(delivery.count ?? 0)],
['delivered / failed / skipped', `${delivery.delivered_count ?? 0} / ${delivery.failed_count ?? 0} / ${delivery.skipped_count ?? 0}`],
['silent-window skips', String(delivery.silent_window_skip_count ?? 0)],
['noise-policy skips', String(delivery.noise_policy_skip_count ?? 0)],
['workbench-only skips', String(delivery.workbench_only_skip_count ?? 0)],
['retried deliveries', String(delivery.retried_delivery_count ?? 0)],
['retry exhausted', String(delivery.retry_exhausted_skip_count ?? 0)],
['transport retried', String(delivery.transport_retried_delivery_count ?? 0)],
['transport retry failed', String(delivery.transport_retry_failed_count ?? 0)],
['policy external allowed', String(delivery.policy_external_allowed_count ?? 0)],
['media attached / linked / unavailable', `${delivery.media_attached_count ?? 0} / ${delivery.media_linked_count ?? 0} / ${delivery.media_unavailable_count ?? 0}`],
['channel disabled', String(delivery.channel_disabled_count ?? 0)],
['channel status counts', formatJsonInline(delivery.channel_status_counts || {})],
['external send attempts', String(delivery.external_attempt_count ?? 0)],
['latest delivery', `${delivery.latest_status || 'n/a'} @ ${delivery.latest_channel || 'n/a'}`],
['latest attempted', formatTimestamp(delivery.latest_attempted_ts)],
]
)
);
grid.appendChild(
buildItemCard(
'Silent Window',
silentWindow.active ? 'warning' : 'ok',
[
['status', silentWindow.active ? 'active' : (silentWindow.enabled ? 'inactive' : 'disabled')],
['window', silentWindow.window_label || 'n/a'],
['timezone', silentWindow.timezone || 'n/a'],
['next allowed', formatTimestamp(silentWindow.next_allowed_ts)],
]
)
);
grid.appendChild(
buildItemCard(
'Alert Feedback',
alertFeedback.negative_count ? 'warning' : 'ok',
[
['feedback rows', String(alertFeedback.count ?? 0)],
['positive / negative', `${alertFeedback.positive_count ?? 0} / ${alertFeedback.negative_count ?? 0}`],
['labels', formatJsonInline(alertFeedback.label_counts || {})],
['latest label', alertFeedback.latest_label || 'n/a'],
['latest feedback', formatTimestamp(alertFeedback.latest_created_ts)],
]
)
);
grid.appendChild(
buildItemCard(
'Visual Feedback',
visualFeedback.negative_count ? 'warning' : 'ok',
[
['feedback rows', String(visualFeedback.count ?? 0)],
['positive / negative', `${visualFeedback.positive_count ?? 0} / ${visualFeedback.negative_count ?? 0}`],
['labels', formatJsonInline(visualFeedback.label_counts || {})],
['latest label', visualFeedback.latest_label || 'n/a'],
['latest feedback', formatTimestamp(visualFeedback.latest_created_ts)],
]
)
);
grid.appendChild(
buildItemCard(
'Visual States',
reviewSummary.latest_visual_state || 'n/a',
[
['review rows', String(reviewSummary.count ?? 0)],
['state counts', formatJsonInline(reviewSummary.state_counts || {})],
['trigger counts', formatJsonInline(reviewSummary.trigger_type_counts || {})],
['latest state', reviewSummary.latest_visual_state || 'n/a'],
['latest trigger', reviewSummary.latest_trigger_type || 'n/a'],
['latest reviewed', formatTimestamp(reviewSummary.latest_reviewed_ts)],
]
)
);
alertQualityPanel.appendChild(grid);
}
function getVisualSnapshotArtifactPath(review) {
const snapshotPayload = review?.snapshot_payload || {};
return snapshotPayload.artifact_path || snapshotPayload?.payload?.artifact_path || review?.snapshot_artifact_path || 'n/a';
}
function getVisualSnapshotBrowserStatus(review) {
const snapshotPayload = review?.snapshot_payload || {};
return snapshotPayload.browser_capture?.status || snapshotPayload?.payload?.browser_capture?.status || 'n/a';
}
function getVisualSnapshotHtmlPath(review) {
const snapshotPayload = review?.snapshot_payload || {};
return snapshotPayload.html_path || snapshotPayload?.payload?.html_path || 'n/a';
}
function getVisualMediaSummary(review) {
return review?.media_evidence_summary || review?.media_evidence || {};
}
function getVisualFeedbackSummary(review) {
const summary = review?.feedback_summary || {};
const labels = summary.labels || {};
const labelParts = Object.entries(labels).map(([label, count]) => `${label}:${count}`);
return {
count: summary.count ?? (Array.isArray(review?.feedback) ? review.feedback.length : 0),
latestLabel: summary.latest_label || 'n/a',
labels: labelParts.length ? labelParts.join(', ') : 'none',
usefulCount: summary.useful_count ?? 0,
misleadingCount: summary.misleading_count ?? 0,
actionableCount: summary.actionable_count ?? 0,
};
}
function renderVisualReviews(reviewRows, decisionPacketId) {
clearNode(visualReviewsPanel);
const items = (reviewRows?.items || []).slice(0, 10);
const latest = items[0] || null;
const latestFeedback = getVisualFeedbackSummary(latest);
const latestMedia = getVisualMediaSummary(latest);
visualReviewsPanel.appendChild(
buildActionBar([
{
label: 'Cleanup Old Captures',
onClick: () => runAction('/trading/visual-watch/cleanup-captures', {
retention_hours: 168,
dry_run: false,
max_delete_files: 500,
}),
},
])
);
visualReviewsPanel.appendChild(
buildInfoGrid([
['decision packet', decisionPacketId || 'n/a'],
['reviews', String(items.length)],
['latest state', latest?.visual_state || 'n/a'],
['latest trigger', latest?.trigger_type || latest?.payload?.trigger_type || 'n/a'],
['latest source', latest?.snapshot_source_name || 'n/a'],
['latest browser capture', getVisualSnapshotBrowserStatus(latest)],
['latest media', latestMedia.status || 'n/a'],
['latest artifact', getVisualSnapshotArtifactPath(latest)],
['latest feedback', `${latestFeedback.count} | ${latestFeedback.latestLabel}`],
['feedback labels', latestFeedback.labels],
])
);
if (!items.length) {
visualReviewsPanel.appendChild(createElement('div', 'empty-state', 'No visual reviews recorded for the current decision packet.'));
return;
}
const grid = createElement('div', 'cards');
items.forEach((review) => {
const feedbackSummary = getVisualFeedbackSummary(review);
const mediaSummary = getVisualMediaSummary(review);
grid.appendChild(
buildItemCard(
`Watch ${review.watch_run_id || 'n/a'}`,
review.visual_state || 'unknown',
[
['trigger', review.trigger_type || review?.payload?.trigger_type || 'n/a'],
['snapshot', review.snapshot_id || 'n/a'],
['source', review.snapshot_source_name || 'n/a'],
['browser capture', getVisualSnapshotBrowserStatus(review)],
['media status', mediaSummary.status || 'n/a'],
['media primary', mediaSummary.primary_path || review?.media_evidence?.primary_item?.path || 'n/a'],
['image path', review.snapshot_image_path || 'n/a'],
['html path', getVisualSnapshotHtmlPath(review)],
['artifact path', getVisualSnapshotArtifactPath(review)],
['reviewed', formatTimestamp(review.reviewed_ts)],
['confidence', formatNumber(review.visual_confidence, 2)],
['anomalies', formatList(review.ui_anomalies || [])],
['feedback', `${feedbackSummary.count} | ${feedbackSummary.latestLabel}`],
['feedback labels', feedbackSummary.labels],
['useful / misleading / actionable', `${feedbackSummary.usefulCount} / ${feedbackSummary.misleadingCount} / ${feedbackSummary.actionableCount}`],
],
[
{
label: 'Useful',
onClick: () => runAction(`/trading/visual-watch/reviews/${review.id}/feedback`, {
label: 'visual_helpful',
note: 'marked from workbench',
created_by: 'local_operator',
payload: { source: 'workbench', feedback_type: 'visual_helpful' },
}),
},
{
label: 'Misleading',
onClick: () => runAction(`/trading/visual-watch/reviews/${review.id}/feedback`, {
label: 'visual_misleading',
note: 'marked from workbench',
created_by: 'local_operator',
payload: { source: 'workbench', feedback_type: 'visual_misleading' },
}),
},
{
label: 'Actionable',
onClick: () => runAction(`/trading/visual-watch/reviews/${review.id}/feedback`, {
label: 'actionable',
note: 'marked from workbench',
created_by: 'local_operator',
payload: { source: 'workbench', feedback_type: 'actionable' },
}),
},
],
review.visual_notes || ''
)
);
});
visualReviewsPanel.appendChild(grid);
}
function renderOperatorConsole(noteRows, reviewPacket) {
clearNode(operatorConsolePanel);
const assistantSummary = reviewPacket?.decision_assistant_summary || window.__latestDecisionAssistantSummary || null;
const focusContext = assistantOperatorNoteDraft.context || getAssistantFocusContext(assistantSummary);
const reviewEntrypoints = assistantSummary?.review_entrypoints || {};
const authorInput = createElement('input');
authorInput.type = 'text';
authorInput.placeholder = 'operator';
authorInput.value = 'local_operator';
const bodyInput = createElement('textarea');
bodyInput.placeholder = 'Add a session, execution, or decision note.';
bodyInput.rows = 4;
bodyInput.className = 'operator-note-textarea';
bodyInput.value = assistantOperatorNoteDraft.body || reviewEntrypoints.focus_note_prefill || '';
const controls = createElement('div', 'actions');
const saveButton = createElement('button', '', 'Save Note');
saveButton.type = 'button';
saveButton.addEventListener('click', async () => {
try {
const noteContext = assistantOperatorNoteDraft.context || focusContext;
await postJson('/trading/operator-notes', {
instrument_id: Number(instrumentIdInput.value || 1),
note_scope: reviewEntrypoints.focus_note_scope || 'workbench',
author: authorInput.value || 'local_operator',
body: bodyInput.value || '',
session_code: noteContext?.session_code || (sessionFilterInput.value === 'all' ? null : sessionFilterInput.value),
candidate_id: noteContext?.candidate_id ?? null,
tags: buildOperatorNoteTags(['workbench', ...(reviewEntrypoints.focus_note_tags || [])], noteContext),
});
bodyInput.value = '';
assistantOperatorNoteDraft = { body: '', context: null };
await refreshDashboard();
} catch (error) {
showErrorPanel(String(error));
}
});
const packetButton = createElement('button', '', 'Generate Review Packet');
packetButton.type = 'button';
packetButton.addEventListener('click', async () => {
try {
await fetchJson(`/trading/review-packet?${queryString({ instrument_id: instrumentIdInput.value || '1', profile_key: assistantDigestProfileKey || 'local_operator' })}`);
await refreshDashboard();
} catch (error) {
showErrorPanel(String(error));
}
});
const prefillFocusButton = createElement('button', '', 'Prefill Focus Note');
prefillFocusButton.type = 'button';
prefillFocusButton.addEventListener('click', () => {
prefillOperatorNote(
reviewEntrypoints.focus_note_prefill || '',
focusContext,
);
});
controls.appendChild(saveButton);
controls.appendChild(packetButton);
controls.appendChild(prefillFocusButton);
operatorConsolePanel.appendChild(authorInput);
operatorConsolePanel.appendChild(bodyInput);
operatorConsolePanel.appendChild(controls);
operatorConsolePanel.appendChild(
buildInfoGrid([
['focus candidate', String(focusContext?.candidate_id ?? 'n/a')],
['focus session', focusContext?.session_code || 'n/a'],
['focus model', focusContext?.model_code || 'n/a'],
['focus note prompt', reviewEntrypoints.focus_note_prompt || 'n/a'],
['review packet', formatTimestamp(reviewPacket?.generated_ts)],
['packet executions', String((reviewPacket?.recent_executions || []).length)],
['packet alerts', String((reviewPacket?.recent_alerts || []).length)],
['packet notes', String((reviewPacket?.recent_notes || []).length)],
['council stance', reviewPacket?.research_council?.payload?.decision?.overall_stance || 'n/a'],
['council confidence', reviewPacket?.research_council?.payload?.decision?.committee_confidence != null
? formatNumber(reviewPacket?.research_council?.payload?.decision?.committee_confidence, 2)
: 'n/a'],
['optimization health', reviewPacket?.research_council_optimization_review?.health_state || 'n/a'],
['optimization summary', reviewPacket?.research_council_optimization_review?.operator_summary || 'n/a'],
['optimization next actions', formatList(reviewPacket?.research_council_optimization_review?.recommended_actions || [])],
])
);
const councilDecision = reviewPacket?.research_council?.payload?.decision || null;
if (councilDecision) {
const bullCase = councilDecision.bull_case || {};
const bearCase = councilDecision.bear_case || {};
const newsAnalysis = councilDecision.news_event_analysis || {};
const visualAnalysis = councilDecision.visual_analysis || {};
operatorConsolePanel.appendChild(
buildItemCard(
'Research Council',
councilDecision.overall_stance || 'observe_only',
[
['research summary', councilDecision.research_summary || 'n/a'],
['operator summary', councilDecision.operator_summary || 'n/a'],
['committee confidence', formatNumber(councilDecision.committee_confidence, 2)],
['agreement', formatList(councilDecision.agreement_points || [])],
['disagreement', formatList(councilDecision.disagreement_points || [])],
['follow-up checks', formatList(councilDecision.follow_up_checks || [])],
['recommended watch', formatList(councilDecision.recommended_watch_items || [])],
['operator questions', formatList(councilDecision.operator_questions || [])],
['execution veto', formatList(councilDecision.execution_veto_signals || [])],
['news/event', newsAnalysis.summary || 'n/a'],
['visual', visualAnalysis.summary || 'n/a'],
],
[],
`Bull: ${bullCase.summary || 'n/a'} | Bear: ${bearCase.summary || 'n/a'}`
)
);
}
const notes = noteRows?.items || [];
const grid = createElement('div', 'cards');
notes.slice(0, 6).forEach((note) => {
grid.appendChild(
buildItemCard(
note.author || 'operator',
note.note_scope || 'general',
[
['session', note.session_code || 'n/a'],
['created', formatTimestamp(note.created_ts)],
['tags', formatList(note.tags || [])],
['body', note.body || ''],
]
)
);
});
if (!notes.length) {
operatorConsolePanel.appendChild(createElement('div', 'empty-state', 'No operator notes yet.'));
} else {
operatorConsolePanel.appendChild(grid);
}
}
function renderPreMarketPlan(plan) {
clearNode(preMarketPlanPanel);
preMarketPlanPanel.appendChild(
buildActionBar([
{
label: 'Generate Active Plan',
onClick: () => runAction('/trading/plans/generate', {
instrument_id: Number(instrumentIdInput.value || 1),
bias_tf: timeframeInput.value || '1m',
setup_tf: timeframeInput.value || '1m',
trigger_tf: timeframeInput.value || '1m',
activate: true,
}),
},
])
);
if (!plan) {
preMarketPlanPanel.appendChild(createElement('div', 'empty-state', 'No active plan for this instrument.'));
return;
}
preMarketPlanPanel.appendChild(
buildInfoGrid([
['narrative', plan.narrative || 'n/a'],
['primary draw', formatJsonInline(plan.primary_draw)],
['secondary draw', formatJsonInline(plan.secondary_draw)],
['bias', plan.bias || 'n/a'],
['allowed sessions', formatList(plan.allowed_sessions || [])],
['invalidations', formatJsonInline(plan.invalidations || [])],
['no-trade conditions', formatList(plan.no_trade_conditions || [])],
['status', plan.status || 'unknown'],
['activated', formatTimestamp(plan.activated_ts)],
])
);
}
function renderCandidates(items) {
clearNode(tradeCandidatesPanel);
tradeCandidatesPanel.appendChild(
buildActionBar([
{
label: 'Run Watch',
onClick: () => runAction('/trading/watch/run', {
instrument_id: Number(instrumentIdInput.value || 1),
setup_tf: timeframeInput.value || '1m',
trigger_tf: timeframeInput.value || '1m',
}),
},
])
);
const filtered = filterBySearch(filterBySession(items, (item) => item.session_code), (item) => [
item.id,
item.status,
item.side,
item.session_code,
item.ai_explanation,
...(item.reason_codes || []),
...(item.missing_conditions || []),
].join(' '));
if (!filtered.length) {
tradeCandidatesPanel.appendChild(createElement('div', 'empty-state', 'No candidate rows match the current filters.'));
return;
}
const trustModels = new Map();
const trustPayload = window.__latestTrustScorePayload || { models: [] };
(trustPayload.models || []).forEach((model) => trustModels.set(model.model_code, model));
const grid = createElement('div', 'cards');
filtered.forEach((candidate) => {
const trustModel = trustModels.get(candidate.model_code) || {};
const executionAllowed = trustModel.execution_allowed !== false && candidate.executable;
const canBuildShadowPaper = !executionAllowed && candidate.executable;
const detail = `quality ${formatNumber(candidate.quality_score)} | ${candidate.ai_explanation || 'no explanation'}`;
const ticketActions = [];
if (executionAllowed) {
ticketActions.push(
{
label: 'Build Paper Ticket',
onClick: () => runAction(`/trading/candidates/${candidate.id}/build-ticket`, {
execution_mode: 'paper',
account_equity: 10000,
risk_pct: 0.01,
}),
},
{
label: 'Build Semi-Auto Ticket',
onClick: () => runAction(`/trading/candidates/${candidate.id}/build-ticket`, {
execution_mode: 'semi_auto',
account_equity: 10000,
risk_pct: 0.01,
}),
}
);
} else if (canBuildShadowPaper) {
ticketActions.push({
label: 'Build Shadow Paper',
onClick: () => runAction(`/trading/candidates/${candidate.id}/build-ticket`, {
execution_mode: 'paper',
account_equity: 10000,
risk_pct: 0.01,
allow_shadow_paper: true,
}),
});
}
grid.appendChild(
buildItemCard(
`Candidate #${candidate.id}`,
candidate.status,
[
['model', candidate.model_code],
['side', candidate.side || 'n/a'],
['session', candidate.session_code || 'n/a'],
['confirmation chain', formatList(candidate.present_conditions || [])],
['missing requirements', formatList(candidate.missing_conditions || [])],
['entry zone', `${formatNumber(candidate.entry_low, 3)} - ${formatNumber(candidate.entry_high, 3)}`],
['stop', formatNumber(candidate.stop_loss, 3)],
['TP1 / TP2', `${formatNumber(candidate.tp1, 3)} / ${formatNumber(candidate.tp2, 3)}`],
['RR TP1 / TP2', `${formatNumber(candidate.rr_tp1)} / ${formatNumber(candidate.rr_tp2)}`],
['expiry', formatTimestamp(candidate.expiry_ts)],
['trust mode', trustModel.operator_mode || 'unknown'],
['management rules', formatJsonInline(candidate.management_rules)],
['evidence links', formatJsonInline(candidate.evidence)],
],
ticketActions,
detail
)
);
});
tradeCandidatesPanel.appendChild(grid);
}
function renderTickets(items) {
clearNode(executionTicketsPanel);
const filtered = filterBySearch(filterBySession(items, (item) => (item.ticket_snapshot || {}).signal?.session_code), (item) => {
const snapshot = item.ticket_snapshot || {};
return [
item.id,
item.status,
item.execution_mode,
snapshot.signal?.side,
snapshot.signal?.session_code,
snapshot.decision?.meta?.ai_explanation,
...(snapshot.decision?.reasons || []),
].join(' ');
});
if (!filtered.length) {
executionTicketsPanel.appendChild(createElement('div', 'empty-state', 'No execution tickets match the current filters.'));
return;
}
const grid = createElement('div', 'cards');
filtered.forEach((ticket) => {
const snapshot = ticket.ticket_snapshot || {};
const signal = snapshot.signal || {};
const decision = snapshot.decision || {};
const riskGovernor = decision.meta?.risk_governor || {};
const riskAmount = Number(snapshot.account_equity || 0) * Number(decision.risk_pct || 0);
const actions = [];
actions.push({
label: 'Risk Check',
onClick: () => runAction(`/trading/tickets/${ticket.id}/risk-check`, {
account_equity: Number(snapshot.account_equity || 10000),
risk_pct: Number(decision.risk_pct || 0.01),
}),
});
if (ticket.status === 'awaiting_confirmation') {
actions.push({
label: 'Confirm',
onClick: () => runAction(`/trading/tickets/${ticket.id}/confirm`, { confirmed_by: 'local_operator' }),
});
}
if (ticket.status === 'confirmed' && ticket.execution_mode === 'paper') {
actions.push({
label: 'Paper Execute',
onClick: () => runAction(`/trading/tickets/${ticket.id}/paper-execute`, { confirmed_by: 'local_operator' }),
});
}
if (ticket.status === 'confirmed' && ticket.execution_mode === 'semi_auto') {
actions.push({
label: 'Semi-Auto Submit',
onClick: () => runAction(`/trading/tickets/${ticket.id}/semi-auto-submit`, { confirmed_by: 'local_operator' }),
});
}
grid.appendChild(
buildItemCard(
`Ticket #${ticket.id}`,
ticket.status,
[
['mode', ticket.execution_mode],
['side', signal.side || 'n/a'],
['entry zone', `${formatNumber(signal.entry_low, 3)} - ${formatNumber(signal.entry_high, 3)}`],
['stop', formatNumber(signal.stop_loss, 3)],
['TP1 / TP2', `${formatNumber(signal.tp1, 3)} / ${formatNumber(signal.tp2, 3)}`],
['RR', `${formatNumber(decision.meta?.tp1 ? Math.abs((Number(decision.meta.tp1) - Number(decision.entry_price || 0)) / Math.max(Math.abs(Number(decision.entry_price || 0) - Number(decision.meta.stop_loss || 0)), 1e-9)) : 0)} / ${formatNumber(decision.meta?.tp2 ? Math.abs((Number(decision.meta.tp2) - Number(decision.entry_price || 0)) / Math.max(Math.abs(Number(decision.entry_price || 0) - Number(decision.meta.stop_loss || 0)), 1e-9)) : 0)}`],
['risk amount', formatNumber(riskAmount, 2)],
['expiry', formatTimestamp(ticket.expires_ts)],
['management rules', formatJsonInline(signal.target_plan?.management_rules || [])],
['risk governor result', formatJsonInline(riskGovernor.reject_codes || [])],
['confirmed by', ticket.confirmed_by || 'n/a'],
['confirmed at', formatTimestamp(ticket.confirmed_at)],
],
actions,
decision.meta?.ai_explanation || ''
)
);
});
executionTicketsPanel.appendChild(grid);
}
function renderExecutions(items) {
clearNode(positionManagementPanel);
positionManagementPanel.appendChild(
buildActionBar([
{
label: 'Reconcile Real Trades',
onClick: () => runAction('/trading/reconcile', {
instrument_id: Number(instrumentIdInput.value || 1),
}),
},
])
);
const filtered = filterExecutions(items);
if (!filtered.length) {
positionManagementPanel.appendChild(createElement('div', 'empty-state', 'No execution rows match the current filters.'));
return;
}
const grid = createElement('div', 'cards');
filtered.forEach((execution) => {
const tpProgress = [
execution.tp1_hit ? 'TP1 hit' : 'TP1 open',
execution.tp2_hit ? 'TP2 hit' : 'TP2 open',
].join(' | ');
grid.appendChild(
buildItemCard(
`Execution #${execution.execution_id}`,
execution.execution_status,
[
['mode', execution.execution_mode],
['side', execution.side || 'n/a'],
['fill state', execution.fill_state || 'n/a'],
['position state', execution.position_state || 'n/a'],
['TP progress', tpProgress],
['stop state', execution.close_reason || 'active'],
['invalidation alerts', formatList(execution.error_tags || [])],
['ticket', execution.execution_ticket_id || 'n/a'],
['opened', formatTimestamp(execution.opened_ts)],
['closed', formatTimestamp(execution.closed_ts)],
['quality', formatNumber(execution.quality_score)],
['real trade mapping', formatJsonInline(execution.reconciliation_state || {})],
['bracket state', formatJsonInline(execution.bracket_state || {})],
['reconciliation', formatJsonInline(execution.reconciliation_state || {})],
],
[
{
label: 'Cancel',
onClick: () => runAction(`/trading/executions/${execution.execution_id}/cancel`, {}),
},
{
label: 'Close',
onClick: () => runAction(`/trading/executions/${execution.execution_id}/close`, {}),
},
{
label: 'Sync',
onClick: () => runAction(`/trading/executions/${execution.execution_id}/sync`, {}),
},
],
execution.ai_explanation || ''
)
);
});
positionManagementPanel.appendChild(grid);
}
function renderPostTradeReview(summary, journalItems, weeklyReview) {
clearNode(postTradeReviewPanel);
postTradeReviewPanel.appendChild(
buildActionBar([
{
label: 'Generate Journal Backfill',
onClick: () => runAction('/trading/journal/generate', {}),
},
])
);
const top = buildInfoGrid([
['entry count', String(summary?.entry_count ?? weeklyReview?.entry_count ?? 0)],
['real trades', String(weeklyReview?.real_trade_count ?? 0)],
['framework execution rate', formatPercent(weeklyReview?.framework_execution_rate)],
['out-of-model rate', formatPercent(weeklyReview?.out_of_model_trade_rate)],
['out-of-model real trades', formatPercent(weeklyReview?.out_of_model_real_trade_rate)],
['risk violation count', String(weeklyReview?.risk_violation_count ?? 0)],
['reconciliation issues', String(weeklyReview?.reconciliation_issue_count ?? 0)],
['high quality session', formatJsonInline(weeklyReview?.high_quality_session)],
['low quality session', formatJsonInline(weeklyReview?.low_quality_session)],
['next actions', formatList(weeklyReview?.next_week_actions || [])],
]);
postTradeReviewPanel.appendChild(top);
const filteredJournal = filterBySession(journalItems, (item) => item.session_code);
if (!filteredJournal.length) {
postTradeReviewPanel.appendChild(createElement('div', 'empty-state', 'No journal entries available for this instrument.'));
return;
}
const grid = createElement('div', 'cards');
filteredJournal.slice(0, 6).forEach((entry) => {
grid.appendChild(
buildItemCard(
`Journal #${entry.id}`,
entry.compliance_state || 'review',
[
['model compliance', String(Boolean(entry.model_compliance))],
['risk compliance', String(!entry.risk_violation)],
['execution violations', formatList(entry.execution_violations || [])],
['model failure', String(Boolean(entry.model_failure))],
['execution failure', String(Boolean(entry.execution_violation))],
['next actions', formatList(entry.next_actions || [])],
],
[],
formatJsonInline(entry.summary || {})
)
);
});
postTradeReviewPanel.appendChild(grid);
}
function drawCandles(items) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!Array.isArray(items) || items.length === 0) {
ctx.fillStyle = '#9db0d3';
ctx.font = '14px sans-serif';
ctx.fillText('No candle data available.', 24, 36);
return;
}
const candles = [...items].reverse();
const highs = candles.map((item) => Number(item.high || 0));
const lows = candles.map((item) => Number(item.low || 0));
const closes = candles.map((item) => Number(item.close || 0));
const minPrice = Math.min(...lows);
const maxPrice = Math.max(...highs);
const range = Math.max(maxPrice - minPrice, 1e-9);
const chartLeft = 40;
const chartRight = canvas.width - 16;
const chartTop = 16;
const chartBottom = canvas.height - 24;
const chartHeight = chartBottom - chartTop;
const chartWidth = chartRight - chartLeft;
ctx.strokeStyle = '#24304f';
ctx.lineWidth = 1;
for (let i = 0; i <= 4; i += 1) {
const y = chartTop + (chartHeight / 4) * i;
ctx.beginPath();
ctx.moveTo(chartLeft, y);
ctx.lineTo(chartRight, y);
ctx.stroke();
}
ctx.strokeStyle = '#4f7cff';
ctx.lineWidth = 2;
ctx.beginPath();
closes.forEach((close, index) => {
const x = chartLeft + (chartWidth * index) / Math.max(closes.length - 1, 1);
const y = chartBottom - ((close - minPrice) / range) * chartHeight;
if (index === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
ctx.fillStyle = '#9db0d3';
ctx.font = '12px sans-serif';
ctx.fillText(maxPrice.toFixed(2), 4, chartTop + 10);
ctx.fillText(minPrice.toFixed(2), 4, chartBottom);
}
function showErrorPanel(message) {
[
marketStatePanel,
runtimeStatusPanel,
decisionPacketPanel,
trustScorePanel,
liveReadinessPanel,
launchReadinessPanel,
sessionFocusPanel,
preMarketPlanPanel,
strategyBacktestPanel,
tradeCandidatesPanel,
executionTicketsPanel,
alertHistoryPanel,
visualReviewsPanel,
positionManagementPanel,
operatorConsolePanel,
postTradeReviewPanel,
alertQualityPanel,
].forEach((panel) => {
clearNode(panel);
panel.appendChild(createElement('div', 'empty-state error-state', message));
});
}
function updateLastUpdated() {
setText(lastUpdated, `Last updated: ${new Date().toLocaleTimeString()}`);
}
function renderDashboardData({
health,
candles,
tradingPlan,
marketState,
runtimeStatus,
runtimeIncidents,
maintenanceSummary,
decisionPacket,
decisionAlerts,
visualReviews,
alertQualitySummary,
operatorDigest,
decisionPacketId,
trustScore,
liveReadiness,
launchReadiness,
sessionView,
strategyBacktests,
tradeCandidates,
executionTickets,
tradingExecutions,
journalSummary,
operatorNotes,
reviewPacket,
journalItems,
weeklyReview,
}) {
window.__latestTrustScorePayload = trustScore;
renderHealth(health);
renderOverview(weeklyReview, tradeCandidates.items || [], executionTickets.items || [], tradingExecutions.items || []);
renderDecisionAssistant(reviewPacket?.decision_assistant_summary || null);
renderMarketState(marketState, tradingExecutions.items || []);
renderRuntimeStatus(runtimeStatus, runtimeIncidents, maintenanceSummary);
renderDecisionPacket(decisionPacket, decisionAlerts);
renderTrustScore(trustScore);
renderLiveReadiness(liveReadiness);
renderLaunchReadiness(launchReadiness);
renderSessionFocus(sessionView);
renderStrategyBacktests(strategyBacktests);
renderPreMarketPlan(tradingPlan);
renderCandidates(tradeCandidates.items || []);
renderTickets(executionTickets.items || []);
renderAlertHistory(decisionAlerts);
renderAlertQuality(alertQualitySummary, operatorDigest);
renderVisualReviews(visualReviews, decisionPacketId);
renderExecutions(tradingExecutions.items || []);
renderOperatorConsole(operatorNotes, reviewPacket);
renderPostTradeReview(journalSummary, journalItems.items || [], weeklyReview);
drawCandles(candles.items || []);
updateActiveFilters();
updateLastUpdated();
}
async function refreshDashboard() {
const instrumentId = instrumentIdInput.value || '1';
const timeframe = timeframeInput.value || '1m';
const limit = limitInput.value || '20';
const backtestInstrumentId = backtestInstrumentIdInput?.value || instrumentId;
const backtestLimit = backtestLimitInput?.value || '10';
const profileKey = assistantDigestProfileKey || assistantPreferenceDraft?.profile_key || 'local_operator';
try {
const [health, candles, tradingPlan, marketState, runtimeStatus, runtimeIncidents, maintenanceSummary, decisionPacket, decisionAlerts, alertQualitySummary, operatorDigest, trustScore, liveReadiness, launchReadiness, sessionView, strategyBacktests, tradeCandidates, executionTickets, tradingExecutions, journalSummary, operatorNotes, reviewPacket, journalItems, weeklyReview] = await Promise.all([
fetchJson('/health'),
fetchJson(`/candles?${queryString({ instrument_id: instrumentId, timeframe, limit })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/plans/latest?${queryString({ instrument_id: instrumentId })}`).catch(() => null),
fetchJson(`/trading/market-state?${queryString({ instrument_id: instrumentId, timeframe })}`).catch(() => ({ market_state: {} })),
fetchJson('/trading/runtime-status').catch(() => ({ scheduler_state: 'unavailable', tasks: {}, current_blockers: ['runtime_status_unavailable'] })),
fetchJson(`/trading/runtime-incidents?${queryString({ limit: 20, refresh: 0 })}`).catch(() => ({ status: 'unavailable', persisted: false, incident_count: 0, severity_counts: {}, source_counts: {}, recommended_actions: [], items: [] })),
fetchJson(`/trading/maintenance-summary?${queryString({ instrument_id: instrumentId, alert_limit: 50, visual_limit: 50, incident_limit: 50 })}`).catch(() => ({ status: 'unavailable', blockers: ['maintenance_summary_unavailable'], warnings: [], maintenance_actions: {}, p23_assertions: {} })),
fetchJson(`/trading/decision-packet?${queryString({ instrument_id: instrumentId })}`).catch(() => ({ status: 'unavailable', action_recommendation: 'monitor' })),
fetchJson(`/trading/alerts?${queryString({ instrument_id: instrumentId, limit: 10 })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/alerts/quality-summary?${queryString({ instrument_id: instrumentId, limit: 50, visual_limit: 50 })}`).catch(() => ({ recent_alert_count: 0, recent_visual_review_count: 0, delivery_summary: {}, alert_feedback_summary: {}, visual_feedback_summary: {}, visual_review_summary: {}, quality_flags: [], operator_summary: 'alert_quality_unavailable' })),
fetchJson(`/trading/alerts/operator-digest?${queryString({ instrument_id: instrumentId, limit: 50, visual_limit: 50, top_limit: 10 })}`).catch(() => ({ status: 'unavailable', summary_counts: {}, review_queue: [], operator_summary: 'operator_digest_unavailable' })),
fetchJson(`/trading/trust-score?${queryString({ instrument_id: instrumentId })}`).catch(() => ({ models: [], whitelist: [], observe_list: [], blacklist: [], next_actions: [] })),
fetchJson(`/trading/live-readiness?${queryString({ instrument_id: instrumentId, timeframe })}`).catch(() => ({ ready_for_real_live: false, blocking_reasons: ['live_readiness_unavailable'], checklist: [] })),
fetchJson(`/trading/launch-readiness?${queryString({ instrument_id: instrumentId, timeframe })}`).catch(() => ({ assisted_trading_ready: false, real_live_ready: false, blocking_reasons: ['launch_readiness_unavailable'], warning_reasons: [], checklist: [], next_actions: [] })),
fetchJson(`/trading/session-view?${queryString({ instrument_id: instrumentId, limit: 12 })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/backtests?${queryString({ instrument_id: backtestInstrumentId, limit: backtestLimit })}`).catch(() => ({ unavailable: true, items: [], latest: null })),
fetchJson(`/trading/candidates?${queryString({ instrument_id: instrumentId, limit })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/tickets?${queryString({ instrument_id: instrumentId, limit })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/executions?${queryString({ instrument_id: instrumentId, limit })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/journal/summary?${queryString({ instrument_id: instrumentId })}`).catch(() => ({ entry_count: 0, next_week_actions: [] })),
fetchJson(`/trading/operator-notes?${queryString({ instrument_id: instrumentId, limit: 10 })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/review-packet?${queryString({ instrument_id: instrumentId, profile_key: profileKey })}`).catch(() => ({ generated_ts: null, recent_executions: [], recent_alerts: [], recent_notes: [] })),
fetchJson(`/trading/journal?${queryString({ instrument_id: instrumentId, limit })}`).catch(() => ({ items: [] })),
fetchJson(`/trading/research/weekly-review?${queryString({ instrument_id: instrumentId })}`).catch(() => ({ entry_count: 0, next_week_actions: [] })),
]);
const decisionPacketId = decisionPacket?.id || reviewPacket?.decision_packet?.id || null;
const visualReviews = decisionPacketId
? await fetchJson(`/trading/visual-watch/reviews?${queryString({ decision_packet_id: decisionPacketId, limit: 10 })}`).catch(() => ({ items: [] }))
: ({ items: [] });
renderDashboardData({
health,
candles,
tradingPlan,
marketState,
runtimeStatus,
runtimeIncidents,
maintenanceSummary,
decisionPacket,
decisionAlerts,
alertQualitySummary,
operatorDigest,
visualReviews,
decisionPacketId,
trustScore,
liveReadiness,
launchReadiness,
sessionView,
strategyBacktests,
tradeCandidates,
executionTickets,
tradingExecutions,
journalSummary,
operatorNotes,
reviewPacket,
journalItems,
weeklyReview,
});
} catch (error) {
showErrorPanel(String(error));
}
}
function configureAutoRefresh() {
if (autoRefreshTimer) {
clearInterval(autoRefreshTimer);
autoRefreshTimer = null;
}
const seconds = Number(autoRefreshSecondsInput.value || 0);
if (seconds > 0) {
autoRefreshTimer = setInterval(refreshDashboard, seconds * 1000);
}
}
refreshBtn.addEventListener('click', refreshDashboard);
backtestRefreshBtn?.addEventListener('click', refreshDashboard);
backtestInstrumentIdInput?.addEventListener('change', refreshDashboard);
backtestLimitInput?.addEventListener('change', refreshDashboard);
executionStatusFilterInput.addEventListener('change', refreshDashboard);
sessionFilterInput.addEventListener('change', refreshDashboard);
searchTextInput.addEventListener('input', refreshDashboard);
trustClassFilterInput.addEventListener('change', refreshDashboard);
autoRefreshSecondsInput.addEventListener('change', configureAutoRefresh);
initializeWorkbenchNavigation();
configureAutoRefresh();
refreshDashboard();