package app

templ Plugin(page string, initialJob string, lane string) {
    {{
        currentPage := page
        if currentPage == "" {
            currentPage = "overview"
        }
        currentLane := lane
        if currentLane == "" {
            currentLane = "default"
        }
        laneTitle := pluginLaneTitle(currentLane)
        laneDescription := pluginLaneDescription(currentLane)
    }}
    <div class="container-fluid" id="plugin-page" data-plugin-page={ currentPage } data-plugin-job={ initialJob } data-plugin-lane={ currentLane }>
        <div class="row mb-4">
            <div class="col-12">
                <div class="d-flex justify-content-between align-items-center flex-wrap gap-2">
                    <div>
                        <h2 class="mb-0"><i class="fas fa-plug me-2"></i>{ laneTitle }</h2>
                        <p class="text-muted mb-0">{ laneDescription }</p>
                    </div>
                    <div class="btn-group">
                        <button type="button" class="btn btn-outline-secondary" id="plugin-refresh-all-btn">
                            <i class="fas fa-sync-alt me-1"></i>Refresh
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mb-3">
            <div class="col-12">
                <ul class="nav nav-tabs" id="plugin-top-tabs">
                    <li class="nav-item">
                        <button type="button" class="nav-link active" data-plugin-top-tab="overview">
                            <i class="fas fa-chart-line me-1"></i>Overview
                        </button>
                    </li>
                </ul>
            </div>
        </div>

        <div class="row mb-3 d-none" id="plugin-subtab-row">
            <div class="col-12">
                <ul class="nav nav-pills gap-2" id="plugin-subtabs">
                    <li class="nav-item">
                        <button type="button" class="nav-link active" data-plugin-subtab="configuration">
                            <i class="fas fa-sliders-h me-1"></i>Configuration
                        </button>
                    </li>
                    <li class="nav-item">
                        <button type="button" class="nav-link" data-plugin-subtab="detection">
                            <i class="fas fa-search me-1"></i>Job Detection
                        </button>
                    </li>
                    <li class="nav-item">
                        <button type="button" class="nav-link" data-plugin-subtab="queue">
                            <i class="fas fa-list me-1"></i>Job Queue
                        </button>
                    </li>
                    <li class="nav-item">
                        <button type="button" class="nav-link" data-plugin-subtab="execution">
                            <i class="fas fa-tasks me-1"></i>Job Execution
                        </button>
                    </li>
                </ul>
            </div>
        </div>

        <div class="plugin-section plugin-section-overview">
            <div class="row mb-4">
                <div class="col-md-3 mb-3">
                    <div class="card border-info h-100">
                        <div class="card-body text-center">
                            <div class="text-uppercase text-muted small mb-1">Workers</div>
                            <h4 class="mb-0" id="plugin-status-workers">0</h4>
                        </div>
                    </div>
                </div>
                <div class="col-md-3 mb-3">
                    <div class="card border-warning h-100">
                        <div class="card-body text-center">
                            <div class="text-uppercase text-muted small mb-1">Active Jobs</div>
                            <h4 class="mb-0" id="plugin-status-active-jobs">0</h4>
                        </div>
                    </div>
                </div>
                <div class="col-md-3 mb-3">
                    <div class="card border-success h-100">
                        <div class="card-body text-center">
                            <div class="text-uppercase text-muted small mb-1">Activities (recent)</div>
                            <h4 class="mb-0" id="plugin-status-activities">0</h4>
                        </div>
                    </div>
                </div>
                <div class="col-md-3 mb-3">
                    <div class="card border-secondary h-100">
                        <div class="card-body text-center">
                            <div class="text-uppercase text-muted small mb-1">Next Run</div>
                            <h4 class="mb-0 plugin-scheduler-next-run">-</h4>
                            <div class="text-muted small plugin-scheduler-next-run-meta"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header">
                            <h5 class="mb-0"><i class="fas fa-chart-bar me-2"></i>Per Job Type Summary</h5>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Job Type</th>
                                            <th>Active Jobs</th>
                                            <th>Recent Activities</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-jobtype-summary-body">
                                        <tr><td colspan="3" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
                            <h5 class="mb-0"><i class="fas fa-clock me-2"></i>Scheduler State</h5>
                            <small class="text-muted">Sequential scheduler with per-job runtime limits</small>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Job Type</th>
                                            <th>Enabled</th>
                                            <th>Detector</th>
                                            <th>In Flight</th>
                                            <th>Max Runtime</th>
                                            <th>Exec Global</th>
                                            <th>Exec/Worker</th>
                                            <th>Executor Workers</th>
                                            <th>Effective Exec</th>
                                            <th>Last Run</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-scheduler-table-body">
                                        <tr><td colspan="10" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header">
                            <h5 class="mb-0"><i class="fas fa-users me-2"></i>Workers</h5>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive" style="max-height: 560px; overflow-y: auto;">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light sticky-top">
                                        <tr>
                                            <th>Worker</th>
                                            <th>Address</th>
                                            <th>Capabilities</th>
                                            <th>Load</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-workers-table-body">
                                        <tr><td colspan="4" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="plugin-section plugin-section-configuration">
            <div class="row mb-4">
                <div class="col-lg-8 mb-3">
                    <div class="card shadow-sm h-100">
                        <div class="card-header d-flex justify-content-between align-items-center">
                            <h5 class="mb-0"><i class="fas fa-sliders-h me-2"></i>Job Type Configuration</h5>
                            <small class="text-muted" id="plugin-config-updated-at">Not loaded</small>
                        </div>
                        <div class="card-body">
                            <div class="mb-3">
                                <div class="small text-muted">Selected Job Type</div>
                                <div class="fw-semibold" id="plugin-selected-job-type">-</div>
                            </div>

                            <div class="mb-3">
                                <div class="d-flex justify-content-between align-items-center mb-2">
                                    <h6 class="mb-0">Descriptor</h6>
                                    <button type="button" class="btn btn-sm btn-outline-secondary" id="plugin-refresh-schema-btn">
                                        <i class="fas fa-cloud-download-alt me-1"></i>Refresh Schema
                                    </button>
                                </div>
                                <div class="alert alert-light border" id="plugin-descriptor-summary">Select a job type to load schema and config.</div>
                            </div>

                            <div class="mb-3">
                                <h6>Admin Config Form</h6>
                                <div id="plugin-admin-config-form" class="plugin-form-root">
                                    <div class="text-muted">No admin form loaded.</div>
                                </div>
                            </div>

                            <div class="mb-3">
                                <h6>Worker Config Form</h6>
                                <div id="plugin-worker-config-form" class="plugin-form-root">
                                    <div class="text-muted">No worker form loaded.</div>
                                </div>
                            </div>

                            <div class="d-flex flex-wrap gap-2">
                                <button type="button" class="btn btn-primary" id="plugin-save-config-btn">
                                    <i class="fas fa-save me-1"></i>Save Config
                                </button>
                                <button type="button" class="btn btn-outline-primary" id="plugin-trigger-detection-btn">
                                    <i class="fas fa-search me-1"></i>Run Detection
                                </button>
                                <button type="button" class="btn btn-outline-success" id="plugin-run-workflow-btn">
                                    <i class="fas fa-play me-1"></i>Run Detect + Execute
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mb-3">
                    <div class="card shadow-sm">
                        <div class="card-header">
                            <h5 class="mb-0"><i class="fas fa-cogs me-2"></i>Job Scheduling Settings</h5>
                        </div>
                        <div class="card-body">
                            <div class="row g-2" id="plugin-admin-settings-form">
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-enabled">Enabled</label>
                                    <div class="form-check form-switch mt-1">
                                        <input class="form-check-input" type="checkbox" id="plugin-admin-enabled"/>
                                    </div>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-detection-interval">Detection Interval (min)</label>
                                    <input type="number" class="form-control" id="plugin-admin-detection-interval" min="0"/>
                                    <div class="form-text">How often to check for new work.</div>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-detection-timeout">Detection Timeout (s)</label>
                                    <input type="number" class="form-control" id="plugin-admin-detection-timeout" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-execution-timeout">Execution Timeout (s)</label>
                                    <input type="number" class="form-control" id="plugin-admin-execution-timeout" min="0"/>
                                    <div class="form-text">Per-attempt deadline for one job. Size-aware tasks may extend this automatically.</div>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-max-runtime">Job Type Max Runtime (s)</label>
                                    <input type="number" class="form-control" id="plugin-admin-max-runtime" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-max-results">Max Jobs / Detection</label>
                                    <input type="number" class="form-control" id="plugin-admin-max-results" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-global-exec">Global Execution Concurrency</label>
                                    <input type="number" class="form-control" id="plugin-admin-global-exec" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-per-worker-exec">Per Worker Concurrency</label>
                                    <input type="number" class="form-control" id="plugin-admin-per-worker-exec" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-retry-limit">Retry Limit</label>
                                    <input type="number" class="form-control" id="plugin-admin-retry-limit" min="0"/>
                                </div>
                                <div class="col-12">
                                    <label class="form-label" for="plugin-admin-retry-backoff">Retry Backoff (s)</label>
                                    <input type="number" class="form-control" id="plugin-admin-retry-backoff" min="0"/>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="card shadow-sm mt-3">
                        <div class="card-header d-flex justify-content-between align-items-center">
                            <h5 class="mb-0"><i class="fas fa-hourglass-half me-2"></i>Next Run</h5>
                            <small class="text-muted">Scheduler</small>
                        </div>
                        <div class="card-body">
                            <div class="h5 mb-1 plugin-scheduler-next-run">-</div>
                            <div class="text-muted small plugin-scheduler-next-run-meta">Not scheduled</div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="row mb-4">
                <div class="col-lg-6 mb-3">
                    <div class="card shadow-sm h-100">
                        <div class="card-header d-flex justify-content-between align-items-center">
                            <h5 class="mb-0"><i class="fas fa-clipboard-check me-2"></i>Run History</h5>
                            <small class="text-muted">Keep last 10 success + last 10 errors</small>
                        </div>
                        <div class="card-body">
                            <div class="row">
                                <div class="col-12 mb-3">
                                    <h6 class="text-success">Successful Runs</h6>
                                    <div class="table-responsive">
                                        <table class="table table-sm table-striped">
                                            <thead>
                                                <tr>
                                                    <th>Time</th>
                                                    <th>Job ID</th>
                                                    <th>Worker</th>
                                                    <th>Duration</th>
                                                </tr>
                                            </thead>
                                            <tbody id="plugin-runs-success-body">
                                                <tr><td colspan="4" class="text-muted">No data</td></tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                                <div class="col-12">
                                    <h6 class="text-danger">Error Runs</h6>
                                    <div class="table-responsive">
                                        <table class="table table-sm table-striped">
                                            <thead>
                                                <tr>
                                                    <th>Time</th>
                                                    <th>Job ID</th>
                                                    <th>Worker</th>
                                                    <th>Error</th>
                                                </tr>
                                            </thead>
                                            <tbody id="plugin-runs-error-body">
                                                <tr><td colspan="4" class="text-muted">No data</td></tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-6 mb-3">
                    <div class="card shadow-sm h-100">
                        <div class="card-header">
                            <h5 class="mb-0"><i class="fas fa-lightbulb me-2"></i>Detection Results</h5>
                        </div>
                        <div class="card-body" id="plugin-detection-results">
                            <div class="text-muted">Run detection to see proposals.</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="plugin-section plugin-section-queue">
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
                            <h5 class="mb-0"><i class="fas fa-list me-2"></i>Job Queue</h5>
                            <div class="d-flex gap-2 align-items-center flex-wrap">
                                <small class="text-muted">States: pending/assigned/running</small>
                            </div>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive" style="max-height: 560px; overflow-y: auto;">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light sticky-top">
                                        <tr>
                                            <th>Job ID</th>
                                            <th>Type</th>
                                            <th>State</th>
                                            <th>Progress</th>
                                            <th>Worker</th>
                                            <th>Updated</th>
                                            <th>Message</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-queue-jobs-table-body">
                                        <tr><td colspan="7" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="plugin-section plugin-section-detection">
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
                            <h5 class="mb-0"><i class="fas fa-search me-2"></i>Detection Jobs</h5>
                            <div class="small text-muted">Detection activities for selected job type</div>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive" style="max-height: 420px; overflow-y: auto;">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light sticky-top">
                                        <tr>
                                            <th>Time</th>
                                            <th>Job Type</th>
                                            <th>Request ID</th>
                                            <th>Worker</th>
                                            <th>Stage</th>
                                            <th>Source</th>
                                            <th>Message</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-detection-table-body">
                                        <tr><td colspan="7" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="plugin-section plugin-section-execution">
            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
                            <h5 class="mb-0"><i class="fas fa-tasks me-2"></i>Execution Jobs</h5>
                            <div class="d-flex gap-2 align-items-center flex-wrap">
                                <select class="form-select form-select-sm" id="plugin-monitor-job-state-filter" style="min-width: 180px;">
                                    <option value="">All States</option>
                                    <option value="assigned">Assigned</option>
                                    <option value="running">Running</option>
                                    <option value="succeeded">Succeeded</option>
                                    <option value="failed">Failed</option>
                                    <option value="canceled">Canceled</option>
                                </select>
                            </div>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive">
                                <table class="table table-hover mb-0">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Job ID</th>
                                            <th>Type</th>
                                            <th>State</th>
                                            <th>Progress</th>
                                            <th>Worker</th>
                                            <th>Updated</th>
                                            <th>Message</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-execution-jobs-table-body">
                                        <tr><td colspan="7" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="row mb-4">
                <div class="col-12">
                    <div class="card shadow-sm">
                        <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
                            <h5 class="mb-0"><i class="fas fa-stream me-2"></i>Execution Activities</h5>
                            <small class="text-muted">Non-detection events only</small>
                        </div>
                        <div class="card-body p-0">
                            <div class="table-responsive" style="max-height: 420px; overflow-y: auto;">
                                <table class="table table-sm table-hover mb-0">
                                    <thead class="table-light sticky-top">
                                        <tr>
                                            <th>Time</th>
                                            <th>Job Type</th>
                                            <th>Job ID</th>
                                            <th>Source</th>
                                            <th>Stage</th>
                                            <th>Message</th>
                                        </tr>
                                    </thead>
                                    <tbody id="plugin-execution-activities-table-body">
                                        <tr><td colspan="6" class="text-muted text-center py-3">Loading...</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="modal fade" id="plugin-job-detail-modal" tabindex="-1" aria-labelledby="plugin-job-detail-modal-label" aria-hidden="true">
        <div class="modal-dialog modal-xl modal-dialog-scrollable">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="plugin-job-detail-modal-label"><i class="fas fa-file-alt me-2"></i>Job Detail</h5>
                    <div class="ms-auto me-2">
                        <button type="button" class="btn btn-outline-danger btn-sm" id="plugin-expire-job-btn" disabled>
                            <i class="fas fa-stop-circle me-1"></i>Expire Job
                        </button>
                    </div>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body" id="plugin-job-detail-content">
                    <div class="text-muted">Select a job to view details.</div>
                </div>
            </div>
        </div>
    </div>

    <style>
        .plugin-section {
            display: none;
        }

        .plugin-section.plugin-section-active {
            display: block;
        }

        .plugin-form-root .card {
            border: 1px solid #dee2e6;
        }
        .plugin-form-root textarea {
            min-height: 12rem;
        }

        .plugin-field-hidden {
            display: none;
        }

        .plugin-capability-badge {
            font-size: 0.72rem;
            margin-right: 0.25rem;
        }

        .plugin-job-progress {
            min-width: 120px;
        }

        .plugin-detection-item {
            border: 1px solid #dee2e6;
            border-radius: 6px;
            padding: 0.5rem 0.75rem;
            margin-bottom: 0.5rem;
            background: #fbfcfd;
        }

        .plugin-job-link {
            text-decoration: none;
        }

        .plugin-job-detail-json {
            max-height: 220px;
            overflow: auto;
            background: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 6px;
            padding: 0.5rem;
            margin-bottom: 0;
            font-size: 0.82rem;
        }
        </style>

        <script>
        (function() {
            var page = document.getElementById('plugin-page');
            if (!page) {
                return;
            }

            var pluginLane = String(page.getAttribute('data-plugin-lane') || '').trim();

            function basePath(path) {
                return (window.__BASE_PATH__ || '') + path;
            }

            var state = {
                selectedJobType: '',
                jobTypes: [],
                lastDetectionByJobType: {},
                initialPage: String(page.getAttribute('data-plugin-page') || 'overview').trim().toLowerCase(),
                initialJob: String(page.getAttribute('data-plugin-job') || '').trim(),
                activeTopTab: 'overview',
                activeSubTab: 'configuration',
                initialNavigationApplied: false,
                monitorExecutionJobState: '',
                workers: [],
                jobs: [],
                activities: [],
                schedulerStates: [],
                schedulerStatus: null,
                allJobs: [],
                allActivities: [],
                loadedJobType: '',
                descriptor: null,
                config: null,
                refreshTimer: null,
            };

            // appendLaneParam appends ?lane= or &lane= to a URL if a lane filter is active.
            function appendLaneParam(url) {
                if (!pluginLane) return url;
                var sep = url.indexOf('?') === -1 ? '?' : '&';
                return url + sep + 'lane=' + encodeURIComponent(pluginLane);
            }

            function getCSRFToken() {
                var meta = document.querySelector('meta[name="csrf-token"]');
                if (!meta) {
                    return '';
                }
                return meta.getAttribute('content') || '';
            }

            function notify(message, level) {
                if (typeof window.showAlert === 'function') {
                    window.showAlert(message, level || 'info');
                    return;
                }
                if (level === 'error') {
                    console.error(message);
                }
                alert(message);
            }

            async function readResponseJSON(response) {
                var bodyText = await response.text();
                if (!bodyText) {
                    return {};
                }
                try {
                    return JSON.parse(bodyText);
                } catch (e) {
                    return { error: bodyText };
                }
            }

            async function pluginRequest(method, url, payload) {
                var headers = {};
                var requestOptions = {
                    method: method,
                    headers: headers,
                };

                if (payload !== undefined && payload !== null) {
                    headers['Content-Type'] = 'application/json';
                    requestOptions.body = JSON.stringify(payload);
                }

                if (method !== 'GET') {
                    var csrf = getCSRFToken();
                    if (csrf) {
                        headers['X-CSRF-Token'] = csrf;
                    }
                }

                var response = await fetch(basePath(url), requestOptions);
                var data = await readResponseJSON(response);
                if (!response.ok) {
                    var message = (data && (data.error || data.message)) ? (data.error || data.message) : ('Request failed: ' + response.status);
                    var requestError = new Error(message);
                    requestError.responseData = data;
                    requestError.responseStatus = response.status;
                    throw requestError;
                }
                return data;
            }

            function textOrDash(value) {
                if (value === null || value === undefined || value === '') {
                    return '-';
                }
                return String(value);
            }

            function escapeHtml(value) {
                if (value === null || value === undefined) {
                    return '';
                }
                return String(value)
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;')
                    .replace(/"/g, '&quot;')
                    .replace(/'/g, '&#039;');
            }

            function encodePath(value) {
                return encodeURIComponent(value || '');
            }

            function normalizeEnum(value) {
                if (value === undefined || value === null) {
                    return '';
                }
                return String(value).toUpperCase();
            }

            function parseTime(value) {
                if (!value) {
                    return '';
                }
                var date = new Date(value);
                if (Number.isNaN(date.getTime())) {
                    return '';
                }
                return date.toLocaleString();
            }

            function normalizeSubTab(value) {
                var normalized = String(value || '').toLowerCase();
                if (normalized === 'configuration' || normalized === 'detection' || normalized === 'queue' || normalized === 'execution') {
                    return normalized;
                }
                return 'configuration';
            }

            function buildPluginURL(topTab, subTab, jobType) {
                var laneName = pluginLane || 'default';
                var laneBase = '/plugin/lanes/' + encodeURIComponent(laneName);
                if (topTab === 'overview') {
                    return laneBase;
                }
                var effectiveSubTab = normalizeSubTab(subTab);
                var path = laneBase + '/' + encodeURIComponent(effectiveSubTab);
                var jt = String(jobType || '').trim();
                if (jt) {
                    path += '?job=' + encodeURIComponent(jt);
                }
                return path;
            }

            function updateURL(replace) {
                var url = basePath(buildPluginURL(state.activeTopTab, state.activeSubTab, state.selectedJobType));
                if (replace) {
                    history.replaceState({ pluginTopTab: state.activeTopTab, pluginSubTab: state.activeSubTab, pluginJob: state.selectedJobType }, '', url);
                } else {
                    history.pushState({ pluginTopTab: state.activeTopTab, pluginSubTab: state.activeSubTab, pluginJob: state.selectedJobType }, '', url);
                }
            }

            // Parse a job type item (string or object) into a safe object shape
            function parseJobTypeItem(item) {
                var jobType = '';
                var displayName = '';
                
                if (typeof item === 'string') {
                    jobType = String(item || '').trim();
                    displayName = jobType;
                } else if (item && typeof item === 'object') {
                    jobType = String(item.job_type || item.jobType || '').trim();
                    displayName = String(item.display_name || item.displayName || jobType || '').trim();
                    if (!displayName) {
                        displayName = jobType;
                    }
                }
                
                return { jobType: jobType, displayName: displayName };
            }

            function topTabKeyForJobType(jobType) {
                var normalized = String(jobType || '').trim();
                if (!normalized) {
                    return '';
                }
                return 'job:' + normalized;
            }

            function parseJobTypeFromTopTab(tabKey) {
                var normalized = String(tabKey || '').trim();
                if (normalized.indexOf('job:') !== 0) {
                    return '';
                }
                return normalized.slice(4);
            }

            function hasJobType(jobType) {
                var normalized = String(jobType || '').trim();
                if (!normalized) {
                    return false;
                }
                var jobTypes = Array.isArray(state.jobTypes) ? state.jobTypes : [];
                for (var i = 0; i < jobTypes.length; i++) {
                    var item = parseJobTypeItem(jobTypes[i]);
                    if (item.jobType === normalized) {
                        return true;
                    }
                }
                return false;
            }

            function applyInitialNavigation() {
                if (state.initialNavigationApplied) {
                    return;
                }
                state.initialNavigationApplied = true;
                state.activeSubTab = normalizeSubTab(state.initialPage);

                if (state.initialPage === 'overview') {
                    state.activeTopTab = 'overview';
                    return;
                }
                if (!Array.isArray(state.jobTypes) || state.jobTypes.length === 0) {
                    state.activeTopTab = 'overview';
                    return;
                }
                // If a specific job type was provided in the URL, use it
                if (state.initialJob && hasJobType(state.initialJob)) {
                    state.selectedJobType = state.initialJob;
                } else {
                    var firstItem = parseJobTypeItem(state.jobTypes[0]);
                    state.selectedJobType = firstItem.jobType;
                }
                state.activeTopTab = topTabKeyForJobType(state.selectedJobType);
            }

            function ensureActiveNavigation() {
                state.activeSubTab = normalizeSubTab(state.activeSubTab);

                if (state.selectedJobType && !hasJobType(state.selectedJobType)) {
                    state.selectedJobType = '';
                    state.descriptor = null;
                    state.config = null;
                }

                var topTabJobType = parseJobTypeFromTopTab(state.activeTopTab);
                if (topTabJobType && !hasJobType(topTabJobType)) {
                    state.activeTopTab = 'overview';
                    topTabJobType = '';
                }

                if (state.activeTopTab === 'overview') {
                    if (!state.selectedJobType && Array.isArray(state.jobTypes) && state.jobTypes.length > 0) {
                        var item = parseJobTypeItem(state.jobTypes[0]);
                        state.selectedJobType = item.jobType;
                    }
                    return;
                }

                if (!topTabJobType && state.selectedJobType) {
                    topTabJobType = state.selectedJobType;
                }
                if (!topTabJobType && Array.isArray(state.jobTypes) && state.jobTypes.length > 0) {
                    var item = parseJobTypeItem(state.jobTypes[0]);
                    topTabJobType = item.jobType;
                }
                if (!topTabJobType) {
                    state.activeTopTab = 'overview';
                    return;
                }

                state.selectedJobType = topTabJobType;
                state.activeTopTab = topTabKeyForJobType(topTabJobType);
            }

            function renderTopTabs() {
                var root = document.getElementById('plugin-top-tabs');
                if (!root) {
                    return;
                }

                var html = '' +
                    '<li class="nav-item">' +
                    '<button type="button" class="nav-link" data-plugin-top-tab="overview">' +
                    '<i class="fas fa-chart-line me-1"></i>Overview' +
                    '</button>' +
                    '</li>';

                var jobTypes = Array.isArray(state.jobTypes) ? state.jobTypes : [];
                for (var i = 0; i < jobTypes.length; i++) {
                    var item = parseJobTypeItem(jobTypes[i]);
                    var jobType = item.jobType;
                    var displayName = item.displayName;
                    
                    if (!jobType) {
                        continue;
                    }
                    html += '' +
                        '<li class="nav-item">' +
                        '<button type="button" class="nav-link" data-plugin-top-tab="' + escapeHtml(topTabKeyForJobType(jobType)) + '">' +
                        escapeHtml(displayName) +
                        '</button>' +
                        '</li>';
                }
                root.innerHTML = html;
            }

            function renderNavigationState() {
                var selectedJobTypeLabel = document.getElementById('plugin-selected-job-type');
                if (selectedJobTypeLabel) {
                    selectedJobTypeLabel.textContent = state.selectedJobType || '-';
                }

                var isOverview = state.activeTopTab === 'overview';
                var subtabRow = document.getElementById('plugin-subtab-row');
                if (subtabRow) {
                    subtabRow.classList.toggle('d-none', isOverview);
                }

                var topTabs = document.querySelectorAll('#plugin-top-tabs [data-plugin-top-tab]');
                for (var i = 0; i < topTabs.length; i++) {
                    var topTab = topTabs[i];
                    var topKey = String(topTab.getAttribute('data-plugin-top-tab') || '');
                    topTab.classList.toggle('active', topKey === state.activeTopTab);
                }

                var subTabs = document.querySelectorAll('#plugin-subtabs [data-plugin-subtab]');
                for (var j = 0; j < subTabs.length; j++) {
                    var subTab = subTabs[j];
                    var subKey = String(subTab.getAttribute('data-plugin-subtab') || '');
                    subTab.classList.toggle('active', !isOverview && subKey === state.activeSubTab);
                }

                function toggleSection(sectionName, visible) {
                    var section = document.querySelector('.plugin-section-' + sectionName);
                    if (!section) {
                        return;
                    }
                    section.classList.toggle('plugin-section-active', !!visible);
                }

                toggleSection('overview', isOverview);
                toggleSection('configuration', !isOverview && state.activeSubTab === 'configuration');
                toggleSection('detection', !isOverview && state.activeSubTab === 'detection');
                toggleSection('queue', !isOverview && state.activeSubTab === 'queue');
                toggleSection('execution', !isOverview && state.activeSubTab === 'execution');
            }

            function renderJobLink(jobID) {
                var normalized = String(jobID || '').trim();
                if (!normalized) {
                    return '<small>-</small>';
                }
                return '<button type="button" class="btn btn-link btn-sm p-0 align-baseline plugin-job-link" data-job-id="' + escapeHtml(normalized) + '">' + escapeHtml(normalized) + '</button>';
            }

            function toPrettyJson(value) {
                if (value === null || value === undefined || value === '') {
                    return '';
                }
                if (typeof value === 'string') {
                    return value;
                }
                try {
                    return JSON.stringify(value, null, 2);
                } catch (e) {
                    return String(value);
                }
            }

            function clonePlainObject(value) {
                if (!value || typeof value !== 'object') {
                    return null;
                }
                try {
                    return JSON.parse(JSON.stringify(value));
                } catch (e) {
                    return null;
                }
            }

            function extractExecutionPlan(job) {
                if (!job || !job.parameters) {
                    return null;
                }
                var plan = job.parameters.execution_plan;
                if (!plan) {
                    return null;
                }
                if (typeof plan === 'string') {
                    try {
                        plan = JSON.parse(plan);
                    } catch (e) {
                        return null;
                    }
                }
                if (typeof plan !== 'object' || Array.isArray(plan)) {
                    return null;
                }
                return plan;
            }

            function removeExecutionPlanForDisplay(parameters) {
                var copy = clonePlainObject(parameters);
                if (!copy) {
                    return parameters;
                }
                if (copy.execution_plan !== undefined) {
                    delete copy.execution_plan;
                }
                if (Object.keys(copy).length === 0) {
                    return null;
                }
                return copy;
            }

            function parseIntOrDefault(value, fallback) {
                var parsed = parseInt(value, 10);
                if (Number.isNaN(parsed)) {
                    return fallback;
                }
                return parsed;
            }

            function normalizeShardIDs(value) {
                if (!Array.isArray(value)) {
                    return [];
                }
                var out = [];
                for (var i = 0; i < value.length; i++) {
                    var parsed = parseIntOrDefault(value[i], -1);
                    if (parsed >= 0) {
                        out.push(parsed);
                    }
                }
                out.sort(function(a, b) { return a - b; });
                return out;
            }

            function classifyShardLabel(shardID, dataShardCount) {
                if (shardID < dataShardCount) {
                    return {
                        kind: 'data',
                        label: String(shardID),
                        className: 'bg-primary',
                        title: 'Data shard ' + shardID,
                    };
                }
                var parityIndex = shardID - dataShardCount;
                return {
                    kind: 'parity',
                    label: String(shardID),
                    className: 'bg-warning text-dark',
                    title: 'Parity shard ' + shardID + ' (index ' + parityIndex + ')',
                };
            }

            function renderShardBadges(shardIDs, dataShardCount) {
                if (!Array.isArray(shardIDs) || shardIDs.length === 0) {
                    return '<span class="text-muted">-</span>';
                }
                var html = '';
                for (var i = 0; i < shardIDs.length; i++) {
                    var shard = classifyShardLabel(shardIDs[i], dataShardCount);
                    html += '<span class="badge me-1 ' + shard.className + '" title="' + escapeHtml(shard.title) + '">' + escapeHtml(shard.label) + '</span>';
                }
                return html;
            }

            function renderExecutionPlan(plan) {
                if (!plan || typeof plan !== 'object') {
                    return '';
                }

                var jobType = String(plan.job_type || '').trim().toLowerCase();
                if (jobType === 'volume_balance') {
                    return renderBalanceExecutionPlan(plan);
                }
                if (jobType !== 'erasure_coding') {
                    var fallbackText = toPrettyJson(plan);
                    if (!fallbackText) {
                        return '';
                    }
                    return '<div class="mb-3"><h6>Execution Plan</h6><pre class="plugin-job-detail-json">' + escapeHtml(fallbackText) + '</pre></div>';
                }

                var dataShards = parseIntOrDefault(plan.data_shards, 10);
                var parityShards = parseIntOrDefault(plan.parity_shards, 4);
                var totalShards = parseIntOrDefault(plan.total_shards, dataShards + parityShards);
                var sources = Array.isArray(plan.sources) ? plan.sources : [];
                var targets = Array.isArray(plan.targets) ? plan.targets : [];
                var assignments = Array.isArray(plan.shard_assignments) ? plan.shard_assignments : [];

                var html = '';
                html += '<div class="mb-3"><h6>Execution Plan</h6>';
                html += '<div class="row g-2 mb-2">' +
                    '<div class="col-md-3"><small><strong>Volume:</strong> ' + escapeHtml(textOrDash(plan.volume_id)) + '</small></div>' +
                    '<div class="col-md-3"><small><strong>Collection:</strong> ' + escapeHtml(textOrDash(plan.collection)) + '</small></div>' +
                    '<div class="col-md-3"><small><strong>Shards:</strong> ' + escapeHtml(String(dataShards)) + '+' + escapeHtml(String(parityShards)) + '</small></div>' +
                    '<div class="col-md-3"><small><strong>Total:</strong> ' + escapeHtml(String(totalShards)) + '</small></div>' +
                    '</div>';

                html += '<div class="small text-muted mb-2">' +
                    '<span class="badge bg-primary me-1">Data</span>' +
                    '<span class="badge bg-warning text-dark me-2">Parity</span>' +
                    'Source and target placement per shard.' +
                    '</div>';

                function renderEndpointsTable(title, endpoints) {
                    if (!endpoints.length) {
                        return '<div class="mb-2"><strong>' + escapeHtml(title) + ':</strong> <span class="text-muted">none</span></div>';
                    }
                    var table = '<div class="table-responsive mb-2"><table class="table table-sm table-striped mb-0">' +
                        '<thead><tr><th>#</th><th>Node</th><th>DC</th><th>Rack</th><th>Volume</th><th>Shards</th></tr></thead><tbody>';
                    for (var i = 0; i < endpoints.length; i++) {
                        var endpoint = endpoints[i] || {};
                        var endpointShards = normalizeShardIDs(endpoint.shard_ids);
                        table += '<tr>' +
                            '<td>' + escapeHtml(String(i + 1)) + '</td>' +
                            '<td><code>' + escapeHtml(textOrDash(endpoint.node)) + '</code></td>' +
                            '<td>' + escapeHtml(textOrDash(endpoint.data_center)) + '</td>' +
                            '<td>' + escapeHtml(textOrDash(endpoint.rack)) + '</td>' +
                            '<td>' + escapeHtml(textOrDash(endpoint.volume_id)) + '</td>' +
                            '<td>' + renderShardBadges(endpointShards, dataShards) + '</td>' +
                            '</tr>';
                    }
                    table += '</tbody></table></div>';
                    return '<div class="mb-2"><strong>' + escapeHtml(title) + '</strong></div>' + table;
                }

                html += renderEndpointsTable('Sources', sources);
                html += renderEndpointsTable('Targets', targets);

                if (assignments.length) {
                    html += '<div class="mb-2"><strong>Shard Assignments</strong></div>';
                    html += '<div class="table-responsive"><table class="table table-sm table-striped mb-0">' +
                        '<thead><tr><th>Shard</th><th>Kind</th><th>Target</th><th>DC</th><th>Rack</th></tr></thead><tbody>';
                    for (var j = 0; j < assignments.length; j++) {
                        var assignment = assignments[j] || {};
                        var shardID = parseIntOrDefault(assignment.shard_id, -1);
                        if (shardID < 0) {
                            continue;
                        }
                        var shard = classifyShardLabel(shardID, dataShards);
                        html += '<tr>' +
                            '<td><span class="badge ' + shard.className + '">' + escapeHtml(shard.label) + '</span></td>' +
                            '<td>' + escapeHtml(textOrDash(assignment.kind || shard.kind)) + '</td>' +
                            '<td><code>' + escapeHtml(textOrDash(assignment.target_node)) + '</code></td>' +
                            '<td>' + escapeHtml(textOrDash(assignment.target_data_center)) + '</td>' +
                            '<td>' + escapeHtml(textOrDash(assignment.target_rack)) + '</td>' +
                            '</tr>';
                    }
                    html += '</tbody></table></div>';
                }

                html += '</div>';
                return html;
            }

            function renderBalanceExecutionPlan(plan) {
                var html = '<div class="mb-3"><h6>Execution Plan</h6>';
                var moves = Array.isArray(plan.moves) ? plan.moves : [];

                if (moves.length === 0) {
                    // Single-move balance job
                    var src = textOrDash(plan.source_node || plan.source_server);
                    var dst = textOrDash(plan.target_node || plan.target_server);
                    var vid = textOrDash(plan.volume_id);
                    var col = textOrDash(plan.collection);
                    html += `<div class="row g-2 mb-2">
                        <div class="col-md-3"><small><strong>Volume:</strong> ${escapeHtml(vid)}</small></div>
                        <div class="col-md-3"><small><strong>Collection:</strong> ${escapeHtml(col)}</small></div>
                        <div class="col-md-3"><small><strong>Source:</strong> <code>${escapeHtml(src)}</code></small></div>
                        <div class="col-md-3"><small><strong>Target:</strong> <code>${escapeHtml(dst)}</code></small></div>
                        </div>`;
                } else {
                    // Batch balance job
                    html += '<div class="mb-2"><span class="badge bg-info">' + escapeHtml(String(moves.length)) + ' moves</span></div>';
                    html += '<div class="table-responsive"><table class="table table-sm table-striped mb-0">' +
                        '<thead><tr><th>#</th><th>Volume</th><th>Source</th><th>Target</th><th>Collection</th></tr></thead><tbody>';
                    for (var i = 0; i < moves.length; i++) {
                        var move = moves[i] || {};
                        html += `<tr>
                            <td>${escapeHtml(String(i + 1))}</td>
                            <td>${escapeHtml(textOrDash(move.volume_id))}</td>
                            <td><code>${escapeHtml(textOrDash(move.source_node))}</code></td>
                            <td><code>${escapeHtml(textOrDash(move.target_node))}</code></td>
                            <td>${escapeHtml(textOrDash(move.collection))}</td>
                        </tr>`;
                    }
                    html += '</tbody></table></div>';
                }

                html += '</div>';
                return html;
            }

            function isActiveJobState(candidateState) {
                var jobState = candidateState;
                if (candidateState && typeof candidateState === 'object' && candidateState.state !== undefined) {
                    jobState = candidateState.state;
                }
                var st = String(jobState || '').toLowerCase();
                return st === 'job_state_pending' || st === 'job_state_assigned' || st === 'job_state_running' ||
                    st === 'pending' || st === 'assigned' || st === 'running' || st === 'in_progress';
            }

            function setExpireButtonState(job) {
                var expireBtn = document.getElementById('plugin-expire-job-btn');
                if (!expireBtn) {
                    return;
                }
                var jobID = job && job.job_id ? String(job.job_id) : '';
                var active = isActiveJobState(job);
                expireBtn.setAttribute('data-job-id', jobID);
                expireBtn.disabled = !jobID || !active;
                if (!jobID) {
                    expireBtn.title = 'Select a job to expire.';
                } else if (!active) {
                    expireBtn.title = 'Job is not active.';
                } else {
                    expireBtn.title = 'Expire job to unblock scheduling.';
                }
            }

            async function expireJob(jobID) {
                var normalizedJobID = String(jobID || '').trim();
                if (!normalizedJobID) {
                    return;
                }

                var reason = window.prompt('Expire job ' + normalizedJobID + '? Optional reason:', 'job expired by admin request');
                if (reason === null) {
                    return;
                }

                var expireBtn = document.getElementById('plugin-expire-job-btn');
                if (expireBtn) {
                    expireBtn.disabled = true;
                }

                try {
                    var response = await pluginRequest('POST', '/api/plugin/jobs/' + encodePath(normalizedJobID) + '/expire', {
                        reason: reason,
                    });
                    if (response && response.expired === false) {
                        notify(response.message || 'Job is not active.', 'info');
                    } else {
                        notify('Job expired: ' + normalizedJobID, 'success');
                    }
                    await refreshJobsAndActivities();
                    await openJobDetail(normalizedJobID);
                } catch (e) {
                    notify('Failed to expire job: ' + e.message, 'error');
                }
            }

            async function openJobDetail(jobID) {
                var normalizedJobID = String(jobID || '').trim();
                if (!normalizedJobID) {
                    return;
                }

                var modalElement = document.getElementById('plugin-job-detail-modal');
                var contentRoot = document.getElementById('plugin-job-detail-content');
                if (!modalElement || !contentRoot) {
                    return;
                }

                var modal;
                if (window.bootstrap && window.bootstrap.Modal) {
                    modal = window.bootstrap.Modal.getOrCreateInstance(modalElement);
                }
                if (modal) {
                    modal.show();
                }

                setExpireButtonState(null);
                contentRoot.innerHTML = '<div class="text-muted">Loading job detail...</div>';
                try {
                    var detail = await pluginRequest('GET', '/api/plugin/jobs/' + encodePath(normalizedJobID) + '/detail?activity_limit=500&related_limit=20');
                    var job = (detail && detail.job) ? detail.job : {};
                    setExpireButtonState(job);
                    var runRecord = detail && detail.run_record ? detail.run_record : null;
                    var activities = (detail && Array.isArray(detail.activities)) ? detail.activities : [];
                    var relatedJobs = (detail && Array.isArray(detail.related_jobs)) ? detail.related_jobs : [];
                    var html = '';

                    html += '<div class="row g-3 mb-3">' +
                        '<div class="col-lg-8">' +
                        '<div><strong>Job ID:</strong> ' + escapeHtml(textOrDash(job.job_id || normalizedJobID)) + '</div>' +
                        '<div><strong>Type:</strong> ' + escapeHtml(textOrDash(job.job_type)) + '</div>' +
                        '<div><strong>State:</strong> ' + escapeHtml(textOrDash(job.state)) + '</div>' +
                        '<div><strong>Worker:</strong> ' + escapeHtml(textOrDash(job.worker_id)) + '</div>' +
                        '<div><strong>Updated:</strong> ' + escapeHtml(parseTime(job.updated_at) || '-') + '</div>' +
                        '</div>' +
                        '<div class="col-lg-4">' +
                        '<div><strong>Attempt:</strong> ' + escapeHtml(textOrDash(job.attempt)) + '</div>' +
                        '<div><strong>Progress:</strong> ' + escapeHtml(String(Math.round(Number(job.progress || 0)))) + '%</div>' +
                        '<div><strong>Created:</strong> ' + escapeHtml(parseTime(job.created_at) || '-') + '</div>' +
                        '<div><strong>Completed:</strong> ' + escapeHtml(parseTime(job.completed_at) || '-') + '</div>' +
                        '</div>' +
                        '</div>';

                    if (job.summary) {
                        html += '<div class="mb-2"><strong>Summary:</strong> ' + escapeHtml(String(job.summary)) + '</div>';
                    }
                    if (job.detail) {
                        html += '<div class="mb-2"><strong>Detail:</strong> ' + escapeHtml(String(job.detail)) + '</div>';
                    }
                    if (job.message) {
                        html += '<div class="mb-2"><strong>Message:</strong> ' + escapeHtml(String(job.message)) + '</div>';
                    }
                    if (job.error_message) {
                        html += '<div class="mb-2 text-danger"><strong>Error:</strong> ' + escapeHtml(String(job.error_message)) + '</div>';
                    }
                    if (job.result_summary) {
                        html += '<div class="mb-2"><strong>Result:</strong> ' + escapeHtml(String(job.result_summary)) + '</div>';
                    }

                    var executionPlan = extractExecutionPlan(job);
                    if (executionPlan) {
                        html += renderExecutionPlan(executionPlan);
                    }

                    var parametersText = toPrettyJson(removeExecutionPlanForDisplay(job.parameters));
                    if (parametersText) {
                        html += '<div class="mb-3"><h6>Parameters</h6><pre class="plugin-job-detail-json">' + escapeHtml(parametersText) + '</pre></div>';
                    }
                    var labelsText = toPrettyJson(job.labels);
                    if (labelsText) {
                        html += '<div class="mb-3"><h6>Labels</h6><pre class="plugin-job-detail-json">' + escapeHtml(labelsText) + '</pre></div>';
                    }
                    var outputsText = toPrettyJson(job.result_output_values);
                    if (outputsText) {
                        html += '<div class="mb-3"><h6>Result Output Values</h6><pre class="plugin-job-detail-json">' + escapeHtml(outputsText) + '</pre></div>';
                    }

                    if (runRecord) {
                        html += '<div class="mb-3"><h6>Run Record</h6>' +
                            '<div><strong>Outcome:</strong> ' + escapeHtml(textOrDash(runRecord.outcome)) + '</div>' +
                            '<div><strong>Duration:</strong> ' + escapeHtml(formatDurationMs(runRecord.duration_ms)) + '</div>' +
                            '<div><strong>Completed:</strong> ' + escapeHtml(parseTime(runRecord.completed_at) || '-') + '</div>' +
                            '<div><strong>Message:</strong> ' + escapeHtml(textOrDash(runRecord.message)) + '</div>' +
                            '</div>';
                    }

                    html += '<h6 class="mt-3">Activity Timeline</h6>';
                    if (!activities.length) {
                        html += '<div class="text-muted mb-3">No activity records.</div>';
                    } else {
                        html += '<div class="table-responsive mb-3"><table class="table table-sm table-striped">' +
                            '<thead><tr><th>Time</th><th>Stage</th><th>Source</th><th>Worker</th><th>Message</th></tr></thead><tbody>';
                        for (var i = 0; i < activities.length; i++) {
                            var activity = activities[i] || {};
                            html += '<tr>' +
                                '<td><small>' + escapeHtml(parseTime(activity.occurred_at) || '-') + '</small></td>' +
                                '<td>' + escapeHtml(textOrDash(activity.stage)) + '</td>' +
                                '<td>' + escapeHtml(textOrDash(activity.source)) + '</td>' +
                                '<td>' + escapeHtml(textOrDash(activity.worker_id)) + '</td>' +
                                '<td><small>' + escapeHtml(textOrDash(activity.message)) + '</small></td>' +
                                '</tr>';
                        }
                        html += '</tbody></table></div>';
                    }

                    if (relatedJobs.length) {
                        html += '<h6>Related Jobs</h6><div class="table-responsive"><table class="table table-sm table-hover">' +
                            '<thead><tr><th>Job ID</th><th>State</th><th>Worker</th><th>Updated</th></tr></thead><tbody>';
                        for (var j = 0; j < relatedJobs.length; j++) {
                            var related = relatedJobs[j] || {};
                            html += '<tr>' +
                                '<td><small>' + escapeHtml(textOrDash(related.job_id)) + '</small></td>' +
                                '<td>' + escapeHtml(textOrDash(related.state)) + '</td>' +
                                '<td>' + escapeHtml(textOrDash(related.worker_id)) + '</td>' +
                                '<td><small>' + escapeHtml(parseTime(related.updated_at) || '-') + '</small></td>' +
                                '</tr>';
                        }
                        html += '</tbody></table></div>';
                    }

                    contentRoot.innerHTML = html;
                } catch (e) {
                    setExpireButtonState(null);
                    contentRoot.innerHTML = '<div class="alert alert-danger mb-0">Failed to load job detail: ' + escapeHtml(e.message) + '</div>';
                }
            }

            function formatDurationMs(value) {
                var ms = Number(value || 0);
                if (!Number.isFinite(ms) || ms <= 0) {
                    return '-';
                }
                if (ms < 1000) {
                    return ms + 'ms';
                }
                var sec = Math.floor(ms / 1000);
                var remainMs = ms % 1000;
                if (sec < 60) {
                    return sec + '.' + String(Math.floor(remainMs / 100)) + 's';
                }
                var min = Math.floor(sec / 60);
                var remainSec = sec % 60;
                return min + 'm ' + remainSec + 's';
            }

            function getWorkerField(worker, name) {
                if (!worker) {
                    return null;
                }
                if (worker[name] !== undefined) {
                    return worker[name];
                }
                var camel = name.charAt(0).toUpperCase() + name.slice(1);
                if (worker[camel] !== undefined) {
                    return worker[camel];
                }
                return null;
            }

            function renderStatus() {
                var allJobs = Array.isArray(state.allJobs) ? state.allJobs : [];
                var allActivities = Array.isArray(state.allActivities) ? state.allActivities : [];

                var activeCount = allJobs.filter(function(job) {
                    return isActiveJobState(job);
                }).length;

                document.getElementById('plugin-status-workers').textContent = String(state.workers.length);
                document.getElementById('plugin-status-active-jobs').textContent = String(activeCount);
                document.getElementById('plugin-status-activities').textContent = String(allActivities.length);
            }

            function renderJobTypeSummary() {
                var tbody = document.getElementById('plugin-jobtype-summary-body');
                if (!tbody) {
                    return;
                }

                var activeByType = {};
                var activityByType = {};

                var allJobs = Array.isArray(state.allJobs) ? state.allJobs : [];
                var allActivities = Array.isArray(state.allActivities) ? state.allActivities : [];

                for (var i = 0; i < allJobs.length; i++) {
                    var job = allJobs[i] || {};
                    var jobType = String(job.job_type || '').trim();
                    if (!jobType) {
                        continue;
                    }
                    var isActive = isActiveJobState(job);
                    if (!isActive) {
                        continue;
                    }
                    if (!activeByType[jobType]) {
                        activeByType[jobType] = 0;
                    }
                    activeByType[jobType]++;
                }

                for (var j = 0; j < allActivities.length; j++) {
                    var activity = allActivities[j] || {};
                    var activityJobType = String(activity.job_type || '').trim();
                    if (!activityJobType) {
                        continue;
                    }
                    if (!activityByType[activityJobType]) {
                        activityByType[activityJobType] = 0;
                    }
                    activityByType[activityJobType]++;
                }

                var known = Array.isArray(state.jobTypes) ? state.jobTypes.slice() : [];
                var seen = {};
                var jobTypes = [];

                for (var k = 0; k < known.length; k++) {
                    var item = parseJobTypeItem(known[k]);
                    var knownType = item && item.jobType ? String(item.jobType).trim() : '';
                    if (!knownType || seen[knownType]) {
                        continue;
                    }
                    seen[knownType] = true;
                    jobTypes.push(knownType);
                }

                Object.keys(activeByType).forEach(function(jobType) {
                    if (!seen[jobType]) {
                        seen[jobType] = true;
                        jobTypes.push(jobType);
                    }
                });
                Object.keys(activityByType).forEach(function(jobType) {
                    if (!seen[jobType]) {
                        seen[jobType] = true;
                        jobTypes.push(jobType);
                    }
                });

                jobTypes.sort();

                if (jobTypes.length === 0) {
                    tbody.innerHTML = '<tr><td colspan=\"3\" class=\"text-muted text-center py-3\">No job types discovered</td></tr>';
                    return;
                }

                var rows = '';
                for (var m = 0; m < jobTypes.length; m++) {
                    var rowType = jobTypes[m];
                    rows += '<tr>' +
                        '<td>' + escapeHtml(rowType) + '</td>' +
                        '<td><span class=\"badge bg-warning text-dark\">' + escapeHtml(String(activeByType[rowType] || 0)) + '</span></td>' +
                        '<td><span class=\"badge bg-info\">' + escapeHtml(String(activityByType[rowType] || 0)) + '</span></td>' +
                        '</tr>';
                }
                tbody.innerHTML = rows;
            }

            function computeEffectiveExecutionCapacity(globalExec, perWorkerExec, executorWorkers) {
                var capacities = [];
                if (globalExec > 0) {
                    capacities.push(globalExec);
                }
                var workerCapacity = perWorkerExec > 0 && executorWorkers > 0 ? (perWorkerExec * executorWorkers) : 0;
                if (workerCapacity > 0) {
                    capacities.push(workerCapacity);
                }
                if (!capacities.length) {
                    return 0;
                }
                var effective = capacities[0];
                for (var i = 1; i < capacities.length; i++) {
                    if (capacities[i] < effective) {
                        effective = capacities[i];
                    }
                }
                return effective;
            }

            function renderSchedulerStates() {
                var tbody = document.getElementById('plugin-scheduler-table-body');
                if (!tbody) {
                    return;
                }

                var states = Array.isArray(state.schedulerStates) ? state.schedulerStates : [];
                if (!states.length) {
                    tbody.innerHTML = '<tr><td colspan="10" class="text-muted text-center py-3">No scheduler state available</td></tr>';
                    return;
                }

                var rows = '';
                for (var i = 0; i < states.length; i++) {
                    var item = states[i] || {};
                    var enabled = !!item.enabled;
                    var inFlight = !!item.detection_in_flight;
                    var detector = item.detector_available ? textOrDash(item.detector_worker_id) : 'No detector';
                    var maxRuntimeSeconds = Number(item.job_type_max_runtime_seconds || 0);
                    var maxRuntimeText = maxRuntimeSeconds > 0 ? (String(maxRuntimeSeconds) + 's') : '-';
                    var globalExec = Number(item.global_execution_concurrency || 0);
                    var perWorkerExec = Number(item.per_worker_execution_concurrency || 0);
                    var executorWorkers = Number(item.executor_worker_count || 0);
                    var effectiveExec = computeEffectiveExecutionCapacity(globalExec, perWorkerExec, executorWorkers);
                    var globalExecText = enabled ? String(globalExec) : '-';
                    var perWorkerExecText = enabled ? String(perWorkerExec) : '-';
                    var executorWorkersText = enabled ? String(executorWorkers) : '-';
                    var effectiveExecText = enabled ? String(effectiveExec) : '-';
                    var lastRunStatus = textOrDash(item.last_run_status);
                    var lastRunTime = parseTime(item.last_run_completed_at);
                    var lastRunText = '-';
                    if (lastRunStatus !== '-' || lastRunTime) {
                        var statusLabel = lastRunStatus !== '-' ? lastRunStatus : 'run';
                        lastRunText = lastRunTime ? (statusLabel + ' @ ' + lastRunTime) : statusLabel;
                    }

                    var enabledBadge = enabled ? '<span class="badge bg-success">Enabled</span>' : '<span class="badge bg-secondary">Disabled</span>';
                    var inFlightBadge = inFlight ? '<span class="badge bg-warning text-dark">Yes</span>' : '<span class="badge bg-light text-dark">No</span>';
                    var policyErrorHtml = '';
                    if (item.policy_error) {
                        policyErrorHtml = '<div><small class="text-danger">' + escapeHtml(String(item.policy_error)) + '</small></div>';
                    }

                    rows += '<tr>' +
                        '<td>' + escapeHtml(textOrDash(item.job_type)) + policyErrorHtml + '</td>' +
                        '<td>' + enabledBadge + '</td>' +
                        '<td><small>' + escapeHtml(detector) + '</small></td>' +
                        '<td>' + inFlightBadge + '</td>' +
                        '<td><small>' + escapeHtml(maxRuntimeText) + '</small></td>' +
                        '<td><small>' + escapeHtml(globalExecText) + '</small></td>' +
                        '<td><small>' + escapeHtml(perWorkerExecText) + '</small></td>' +
                        '<td><small>' + escapeHtml(executorWorkersText) + '</small></td>' +
                        '<td><small>' + escapeHtml(effectiveExecText) + '</small></td>' +
                        '<td><small>' + escapeHtml(lastRunText) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function renderSchedulerStatus() {
                var valueNodes = document.querySelectorAll('.plugin-scheduler-next-run');
                if (!valueNodes.length) {
                    return;
                }
                var metaNodes = document.querySelectorAll('.plugin-scheduler-next-run-meta');
                var status = state.schedulerStatus || {};
                var nextRun = parseTime(status.next_detection_at);
                var display = nextRun || '-';
                valueNodes.forEach(function(node) {
                    node.textContent = display;
                });
                var metaText = nextRun ? 'Local time' : 'Not scheduled';
                if (metaNodes.length) {
                    metaNodes.forEach(function(node) {
                        node.textContent = metaText;
                    });
                }
            }

            function renderWorkers() {
                var tbody = document.getElementById('plugin-workers-table-body');
                if (!state.workers.length) {
                    tbody.innerHTML = '<tr><td colspan="4" class="text-muted text-center py-3">No connected workers</td></tr>';
                    return;
                }

                var rows = '';
                for (var i = 0; i < state.workers.length; i++) {
                    var worker = state.workers[i];
                    var workerID = textOrDash(getWorkerField(worker, 'workerID'));
                    var address = textOrDash(getWorkerField(worker, 'address'));
                    var caps = getWorkerField(worker, 'capabilities') || {};
                    var capBadges = [];

                    Object.keys(caps).sort().forEach(function(jobType) {
                        var cap = caps[jobType] || {};
                        var labels = [];
                        if (cap.can_detect) {
                            labels.push('D');
                        }
                        if (cap.can_execute) {
                            labels.push('E');
                        }
                        var text = jobType;
                        if (labels.length) {
                            text += ' (' + labels.join('/') + ')';
                        }
                        capBadges.push('<span class="badge bg-secondary plugin-capability-badge">' + escapeHtml(text) + '</span>');
                    });

                    if (!capBadges.length) {
                        capBadges.push('<span class="text-muted">-</span>');
                    }

                    var heartbeat = getWorkerField(worker, 'heartbeat') || {};
                    var detUsed = Number(heartbeat.detection_slots_used || heartbeat.DetectionSlotsUsed || 0);
                    var detTotal = Number(heartbeat.detection_slots_total || heartbeat.DetectionSlotsTotal || 0);
                    var execUsed = Number(heartbeat.execution_slots_used || heartbeat.ExecutionSlotsUsed || 0);
                    var execTotal = Number(heartbeat.execution_slots_total || heartbeat.ExecutionSlotsTotal || 0);
                    var runningWork = heartbeat.running_work || heartbeat.RunningWork || [];
                    var queuedByType = heartbeat.queued_jobs_by_type || heartbeat.QueuedJobsByType || {};
                    var queuedTotal = 0;
                    Object.keys(queuedByType || {}).forEach(function(jobType) {
                        var queuedCount = Number(queuedByType[jobType] || 0);
                        if (Number.isFinite(queuedCount) && queuedCount > 0) {
                            queuedTotal += queuedCount;
                        }
                    });
                    var loadLines = [];
                    loadLines.push('Detect: ' + String(detUsed) + '/' + String(detTotal));
                    loadLines.push('Execute: ' + String(execUsed) + '/' + String(execTotal));
                    loadLines.push('Running: ' + String(Array.isArray(runningWork) ? runningWork.length : 0));
                    loadLines.push('Queued: ' + String(queuedTotal));

                    rows += '<tr>' +
                        '<td><div class="fw-semibold">' + escapeHtml(workerID) + '</div></td>' +
                        '<td><small>' + escapeHtml(address) + '</small></td>' +
                        '<td>' + capBadges.join('') + '</td>' +
                        '<td><small>' + escapeHtml(loadLines.join(' | ')) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function normalizeJobStateForFilter(value) {
                var normalized = String(value || '').toLowerCase();
                if (normalized.indexOf('job_state_') === 0) {
                    normalized = normalized.slice('job_state_'.length);
                }
                return normalized;
            }

            function matchesExecutionStateFilter(jobState, selectedFilter) {
                var target = normalizeJobStateForFilter(selectedFilter);
                if (!target) {
                    return true;
                }
                var actual = normalizeJobStateForFilter(jobState);
                if (actual === target) {
                    return true;
                }
                if (target === 'running' && actual === 'in_progress') {
                    return true;
                }
                return false;
            }

            function isDetectionActivitySource(source) {
                var normalized = String(source || '').toLowerCase();
                if (!normalized) {
                    return false;
                }
                if (normalized === 'worker_detection') {
                    return true;
                }
                return normalized.indexOf('detector') >= 0;
            }

            function renderExecutionJobs() {
                var tbody = document.getElementById('plugin-execution-jobs-table-body');
                if (!tbody) {
                    return;
                }

                var filteredJobs = [];
                var allJobs = Array.isArray(state.allJobs) ? state.allJobs : [];
                for (var i = 0; i < allJobs.length; i++) {
                    var job = allJobs[i] || {};
                    var jobType = String(job.job_type || '').trim();
                    if (state.selectedJobType && jobType !== state.selectedJobType) {
                        continue;
                    }
                    if (!matchesExecutionStateFilter(job.state, state.monitorExecutionJobState)) {
                        continue;
                    }
                    filteredJobs.push(job);
                }

                if (!filteredJobs.length) {
                    tbody.innerHTML = '<tr><td colspan="7" class="text-muted text-center py-3">No execution jobs tracked yet</td></tr>';
                    return;
                }

                var rows = '';
                for (var j = 0; j < filteredJobs.length; j++) {
                    var executionJob = filteredJobs[j] || {};
                    var progress = Number(executionJob.progress || 0);
                    if (!Number.isFinite(progress) || progress < 0) {
                        progress = 0;
                    }
                    if (progress > 100) {
                        progress = 100;
                    }

                    var barClass = 'bg-info';
                    var stateText = String(executionJob.state || 'unknown').toLowerCase();
                    if (stateText.indexOf('failed') >= 0) {
                        barClass = 'bg-danger';
                    } else if (stateText.indexOf('succeed') >= 0 || stateText.indexOf('complete') >= 0) {
                        barClass = 'bg-success';
                    } else if (stateText.indexOf('run') >= 0 || stateText.indexOf('progress') >= 0) {
                        barClass = 'bg-warning';
                    }

                    var jobTypeCell = escapeHtml(textOrDash(executionJob.job_type));
                    var execLabels = executionJob.labels || {};
                    if (execLabels.batch === 'true' && execLabels.batch_size) {
                        jobTypeCell += ' <span class="badge bg-info">' + escapeHtml(execLabels.batch_size) + ' moves</span>';
                    }

                    rows += '<tr>' +
                        '<td>' + renderJobLink(executionJob.job_id) + '</td>' +
                        '<td>' + jobTypeCell + '</td>' +
                        '<td><span class="badge bg-light text-dark">' + escapeHtml(textOrDash(executionJob.state)) + '</span></td>' +
                        '<td class="plugin-job-progress"><div class="progress" style="height: 14px;"><div class="progress-bar ' + barClass + '" role="progressbar" style="width:' + progress + '%">' + Math.round(progress) + '%</div></div></td>' +
                        '<td><small>' + escapeHtml(textOrDash(executionJob.worker_id)) + '</small></td>' +
                        '<td><small>' + escapeHtml(parseTime(executionJob.updated_at) || '-') + '</small></td>' +
                        '<td><small>' + escapeHtml(textOrDash(executionJob.message)) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function renderQueueJobs() {
                var tbody = document.getElementById('plugin-queue-jobs-table-body');
                if (!tbody) {
                    return;
                }

                var filteredJobs = [];
                var allJobs = Array.isArray(state.allJobs) ? state.allJobs : [];
                for (var i = 0; i < allJobs.length; i++) {
                    var queueJob = allJobs[i] || {};
                    var queueJobType = String(queueJob.job_type || '').trim();
                    if (state.selectedJobType && queueJobType !== state.selectedJobType) {
                        continue;
                    }
                    var normalizedState = normalizeJobStateForFilter(queueJob.state);
                    if (normalizedState !== 'pending' && normalizedState !== 'assigned' && normalizedState !== 'running' && normalizedState !== 'in_progress') {
                        continue;
                    }
                    filteredJobs.push(queueJob);
                }

                if (!filteredJobs.length) {
                    tbody.innerHTML = '<tr><td colspan="7" class="text-muted text-center py-3">No queued/active jobs</td></tr>';
                    return;
                }

                var rows = '';
                for (var j = 0; j < filteredJobs.length; j++) {
                    var queueItem = filteredJobs[j] || {};
                    var progress = Number(queueItem.progress || 0);
                    if (!Number.isFinite(progress) || progress < 0) {
                        progress = 0;
                    }
                    if (progress > 100) {
                        progress = 100;
                    }

                    var barClass = 'bg-warning';
                    var queueStateText = String(queueItem.state || 'unknown').toLowerCase();
                    if (queueStateText.indexOf('run') >= 0 || queueStateText.indexOf('progress') >= 0) {
                        barClass = 'bg-info';
                    }

                    rows += '<tr>' +
                        '<td>' + renderJobLink(queueItem.job_id) + '</td>' +
                        '<td>' + escapeHtml(textOrDash(queueItem.job_type)) + '</td>' +
                        '<td><span class="badge bg-light text-dark">' + escapeHtml(textOrDash(queueItem.state)) + '</span></td>' +
                        '<td class="plugin-job-progress"><div class="progress" style="height: 14px;"><div class="progress-bar ' + barClass + '" role="progressbar" style="width:' + progress + '%">' + Math.round(progress) + '%</div></div></td>' +
                        '<td><small>' + escapeHtml(textOrDash(queueItem.worker_id)) + '</small></td>' +
                        '<td><small>' + escapeHtml(parseTime(queueItem.updated_at) || '-') + '</small></td>' +
                        '<td><small>' + escapeHtml(textOrDash(queueItem.message)) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function renderDetectionJobs() {
                var tbody = document.getElementById('plugin-detection-table-body');
                if (!tbody) {
                    return;
                }

                var filteredActivities = [];
                var allActivities = Array.isArray(state.allActivities) ? state.allActivities : [];
                for (var i = 0; i < allActivities.length; i++) {
                    var activity = allActivities[i] || {};
                    var jobType = String(activity.job_type || '').trim();
                    if (state.selectedJobType && jobType !== state.selectedJobType) {
                        continue;
                    }
                    if (!isDetectionActivitySource(activity.source)) {
                        continue;
                    }
                    filteredActivities.push(activity);
                }

                if (!filteredActivities.length) {
                    tbody.innerHTML = '<tr><td colspan="7" class="text-muted text-center py-3">No detection jobs tracked yet</td></tr>';
                    return;
                }

                var rows = '';
                for (var j = 0; j < filteredActivities.length; j++) {
                    var detectionActivity = filteredActivities[j] || {};
                    rows += '<tr>' +
                        '<td><small>' + escapeHtml(parseTime(detectionActivity.occurred_at) || '-') + '</small></td>' +
                        '<td>' + escapeHtml(textOrDash(detectionActivity.job_type)) + '</td>' +
                        '<td><small>' + escapeHtml(textOrDash(detectionActivity.request_id)) + '</small></td>' +
                        '<td><small>' + escapeHtml(textOrDash(detectionActivity.worker_id)) + '</small></td>' +
                        '<td>' + escapeHtml(textOrDash(detectionActivity.stage)) + '</td>' +
                        '<td><span class="badge bg-light text-dark">' + escapeHtml(textOrDash(detectionActivity.source)) + '</span></td>' +
                        '<td><small>' + escapeHtml(textOrDash(detectionActivity.message)) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function renderExecutionActivities() {
                var tbody = document.getElementById('plugin-execution-activities-table-body');
                if (!tbody) {
                    return;
                }

                var filteredActivities = [];
                var allActivities = Array.isArray(state.allActivities) ? state.allActivities : [];
                for (var i = 0; i < allActivities.length; i++) {
                    var activity = allActivities[i] || {};
                    if (isDetectionActivitySource(activity.source)) {
                        continue;
                    }
                    var jobType = String(activity.job_type || '').trim();
                    if (state.selectedJobType && jobType !== state.selectedJobType) {
                        continue;
                    }
                    filteredActivities.push(activity);
                }

                if (!filteredActivities.length) {
                    tbody.innerHTML = '<tr><td colspan="6" class="text-muted text-center py-3">No execution activities yet</td></tr>';
                    return;
                }

                var rows = '';
                for (var j = 0; j < filteredActivities.length; j++) {
                    var executionActivity = filteredActivities[j] || {};
                    rows += '<tr>' +
                        '<td><small>' + escapeHtml(parseTime(executionActivity.occurred_at) || '-') + '</small></td>' +
                        '<td>' + escapeHtml(textOrDash(executionActivity.job_type)) + '</td>' +
                        '<td>' + renderJobLink(executionActivity.job_id) + '</td>' +
                        '<td><span class="badge bg-light text-dark">' + escapeHtml(textOrDash(executionActivity.source)) + '</span></td>' +
                        '<td>' + escapeHtml(textOrDash(executionActivity.stage)) + '</td>' +
                        '<td><small>' + escapeHtml(textOrDash(executionActivity.message)) + '</small></td>' +
                        '</tr>';
                }

                tbody.innerHTML = rows;
            }

            function getSelectValueArray(selectEl) {
                if (!selectEl) {
                    return [];
                }
                var values = [];
                for (var i = 0; i < selectEl.options.length; i++) {
                    if (selectEl.options[i].selected) {
                        values.push(selectEl.options[i].value);
                    }
                }
                return values;
            }

            function configValueToNative(configValue) {
                if (!configValue || typeof configValue !== 'object') {
                    return null;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'bool_value')) {
                    return !!configValue.bool_value;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'int64_value')) {
                    return configValue.int64_value;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'double_value')) {
                    return configValue.double_value;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'string_value')) {
                    return configValue.string_value;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'bytes_value')) {
                    return configValue.bytes_value;
                }
                if (Object.prototype.hasOwnProperty.call(configValue, 'duration_value')) {
                    return configValue.duration_value;
                }
                if (configValue.string_list && Array.isArray(configValue.string_list.values)) {
                    return configValue.string_list.values.slice();
                }
                if (configValue.int64_list && Array.isArray(configValue.int64_list.values)) {
                    return configValue.int64_list.values.slice();
                }
                if (configValue.double_list && Array.isArray(configValue.double_list.values)) {
                    return configValue.double_list.values.slice();
                }
                if (configValue.bool_list && Array.isArray(configValue.bool_list.values)) {
                    return configValue.bool_list.values.slice();
                }
                if (configValue.list_value && Array.isArray(configValue.list_value.values)) {
                    return configValue.list_value.values.map(function(v) {
                        return configValueToNative(v);
                    });
                }
                if (configValue.map_value && configValue.map_value.fields) {
                    var out = {};
                    Object.keys(configValue.map_value.fields).forEach(function(k) {
                        out[k] = configValueToNative(configValue.map_value.fields[k]);
                    });
                    return out;
                }
                return null;
            }

            function inferConfigValue(value) {
                if (value === null || value === undefined) {
                    return { string_value: '' };
                }
                if (typeof value === 'boolean') {
                    return { bool_value: value };
                }
                if (typeof value === 'number') {
                    if (Number.isInteger(value)) {
                        return { int64_value: String(value) };
                    }
                    return { double_value: value };
                }
                if (typeof value === 'string') {
                    return { string_value: value };
                }
                if (Array.isArray(value)) {
                    var listValues = value.map(function(item) {
                        return inferConfigValue(item);
                    });
                    return { list_value: { values: listValues } };
                }
                if (typeof value === 'object') {
                    var fields = {};
                    Object.keys(value).forEach(function(key) {
                        fields[key] = inferConfigValue(value[key]);
                    });
                    return { map_value: { fields: fields } };
                }
                return { string_value: String(value) };
            }

            function nativeToConfigValue(value, fieldType, widget, field) {
                var normalizedFieldType = normalizeEnum(fieldType);
                var normalizedWidget = normalizeEnum(widget);

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_BOOL') {
                    return { bool_value: !!value };
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_INT64') {
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }
                    var intValue = parseInt(value, 10);
                    if (Number.isNaN(intValue)) {
                        throw new Error('Invalid int64 value for field ' + field.name);
                    }
                    return { int64_value: String(intValue) };
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_DOUBLE') {
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }
                    var doubleValue = parseFloat(value);
                    if (Number.isNaN(doubleValue)) {
                        throw new Error('Invalid number for field ' + field.name);
                    }
                    return { double_value: doubleValue };
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_DURATION') {
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }
                    var text = String(value).trim();
                    if (!text) {
                        return null;
                    }
                    if (/^\d+$/.test(text)) {
                        text += 's';
                    }
                    return { duration_value: text };
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_LIST') {
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }

                    if (normalizedWidget === 'CONFIG_WIDGET_MULTI_SELECT' && Array.isArray(value)) {
                        return { string_list: { values: value } };
                    }

                    if (typeof value === 'string') {
                        try {
                            var parsed = JSON.parse(value);
                            if (!Array.isArray(parsed)) {
                                throw new Error('Expected JSON array');
                            }
                            return inferConfigValue(parsed);
                        } catch (e) {
                            throw new Error('Invalid JSON list for field ' + field.name + ': ' + e.message);
                        }
                    }
                    return inferConfigValue(value);
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_OBJECT') {
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }
                    if (typeof value === 'string') {
                        try {
                            var parsedObject = JSON.parse(value);
                            if (!parsedObject || typeof parsedObject !== 'object' || Array.isArray(parsedObject)) {
                                throw new Error('Expected JSON object');
                            }
                            return inferConfigValue(parsedObject);
                        } catch (e) {
                            throw new Error('Invalid JSON object for field ' + field.name + ': ' + e.message);
                        }
                    }
                    return inferConfigValue(value);
                }

                if (normalizedFieldType === 'CONFIG_FIELD_TYPE_ENUM') {
                    if (normalizedWidget === 'CONFIG_WIDGET_MULTI_SELECT') {
                        if (!value || !value.length) {
                            return null;
                        }
                        return { string_list: { values: value } };
                    }
                    if (value === '' || value === null || value === undefined) {
                        return null;
                    }
                    return { string_value: String(value) };
                }

                if (value === '' || value === null || value === undefined) {
                    return null;
                }

                return { string_value: String(value) };
            }

            function toInputID(scope, fieldName) {
                return 'plugin-' + scope + '-field-' + String(fieldName || '').replace(/[^a-zA-Z0-9_-]/g, '_');
            }

            function resolveFieldConfigValue(scope, field) {
                if (!field || !field.name) {
                    return null;
                }
                var fromConfig = null;
                if (state.config) {
                    if (scope === 'admin' && state.config.admin_config_values) {
                        fromConfig = state.config.admin_config_values[field.name];
                    }
                    if (scope === 'worker' && state.config.worker_config_values) {
                        fromConfig = state.config.worker_config_values[field.name];
                    }
                }
                if (fromConfig) {
                    return fromConfig;
                }

                var formDefaults = null;
                if (scope === 'admin' && state.descriptor && state.descriptor.admin_config_form && state.descriptor.admin_config_form.default_values) {
                    formDefaults = state.descriptor.admin_config_form.default_values[field.name];
                }
                if (scope === 'worker' && state.descriptor && state.descriptor.worker_config_form && state.descriptor.worker_config_form.default_values) {
                    formDefaults = state.descriptor.worker_config_form.default_values[field.name];
                }
                if (formDefaults) {
                    return formDefaults;
                }

                if (scope === 'worker' && state.descriptor && state.descriptor.worker_default_values) {
                    return state.descriptor.worker_default_values[field.name] || null;
                }

                return null;
            }

            function renderFieldInput(scope, field, value) {
                var inputID = toInputID(scope, field.name);
                var normalizedType = normalizeEnum(field.field_type);
                var normalizedWidget = normalizeEnum(field.widget);
                var input;

                if (normalizedType === 'CONFIG_FIELD_TYPE_BOOL' || normalizedWidget === 'CONFIG_WIDGET_TOGGLE') {
                    input = document.createElement('input');
                    input.type = 'checkbox';
                    input.className = 'form-check-input';
                    input.id = inputID;
                    input.checked = !!value;
                } else if ((normalizedType === 'CONFIG_FIELD_TYPE_ENUM' && normalizedWidget === 'CONFIG_WIDGET_MULTI_SELECT') || normalizedWidget === 'CONFIG_WIDGET_MULTI_SELECT') {
                    input = document.createElement('select');
                    input.className = 'form-select';
                    input.id = inputID;
                    input.multiple = true;
                    var selected = Array.isArray(value) ? value : [];
                    var options = Array.isArray(field.options) ? field.options : [];
                    for (var i = 0; i < options.length; i++) {
                        var option = document.createElement('option');
                        option.value = options[i].value || '';
                        option.textContent = options[i].label || options[i].value || '';
                        if (selected.indexOf(option.value) >= 0) {
                            option.selected = true;
                        }
                        input.appendChild(option);
                    }
                } else if (normalizedType === 'CONFIG_FIELD_TYPE_ENUM' || normalizedWidget === 'CONFIG_WIDGET_SELECT') {
                    input = document.createElement('select');
                    input.className = 'form-select';
                    input.id = inputID;
                    var blankOption = document.createElement('option');
                    blankOption.value = '';
                    blankOption.textContent = '-- select --';
                    input.appendChild(blankOption);
                    var enumOptions = Array.isArray(field.options) ? field.options : [];
                    for (var j = 0; j < enumOptions.length; j++) {
                        var enumOption = document.createElement('option');
                        enumOption.value = enumOptions[j].value || '';
                        enumOption.textContent = enumOptions[j].label || enumOptions[j].value || '';
                        if (String(value) === enumOption.value) {
                            enumOption.selected = true;
                        }
                        input.appendChild(enumOption);
                    }
                } else if (normalizedType === 'CONFIG_FIELD_TYPE_INT64' || normalizedType === 'CONFIG_FIELD_TYPE_DOUBLE' || normalizedWidget === 'CONFIG_WIDGET_NUMBER') {
                    input = document.createElement('input');
                    input.type = 'number';
                    if (normalizedType === 'CONFIG_FIELD_TYPE_DOUBLE') {
                        input.step = 'any';
                    }
                    input.className = 'form-control';
                    input.id = inputID;
                    if (value !== null && value !== undefined && value !== '') {
                        input.value = String(value);
                    }
                } else if (normalizedType === 'CONFIG_FIELD_TYPE_LIST' || normalizedType === 'CONFIG_FIELD_TYPE_OBJECT' || normalizedWidget === 'CONFIG_WIDGET_TEXTAREA') {
                    input = document.createElement('textarea');
                    input.className = 'form-control';
                    input.id = inputID;
                    input.rows = 4;
                    if (normalizedType === 'CONFIG_FIELD_TYPE_LIST' || normalizedType === 'CONFIG_FIELD_TYPE_OBJECT') {
                        input.placeholder = normalizedType === 'CONFIG_FIELD_TYPE_LIST' ? '[...]' : '{...}';
                    }
                    if (value !== null && value !== undefined && value !== '') {
                        if (typeof value === 'object') {
                            input.value = JSON.stringify(value, null, 2);
                        } else {
                            input.value = String(value);
                        }
                    }
                } else {
                    input = document.createElement('input');
                    input.className = 'form-control';
                    input.id = inputID;
                    if (normalizedWidget === 'CONFIG_WIDGET_PASSWORD' || field.sensitive) {
                        input.type = 'password';
                    } else {
                        input.type = 'text';
                    }
                    if (value !== null && value !== undefined && value !== '') {
                        input.value = String(value);
                    }
                }

                if (field.placeholder && input.tagName === 'INPUT') {
                    input.placeholder = field.placeholder;
                }
                if (field.placeholder && input.tagName === 'TEXTAREA') {
                    input.placeholder = field.placeholder;
                }

                if (field.required) {
                    input.required = true;
                }
                if (field.read_only) {
                    input.disabled = true;
                }

                return input;
            }

            function renderConfigForm(scope, rootID, form) {
                var root = document.getElementById(rootID);
                if (!root) {
                    return;
                }

                root.innerHTML = '';
                if (!form || !Array.isArray(form.sections) || form.sections.length === 0) {
                    root.innerHTML = '<div class="text-muted">No fields provided by descriptor.</div>';
                    return;
                }

                for (var s = 0; s < form.sections.length; s++) {
                    var section = form.sections[s] || {};
                    var sectionCard = document.createElement('div');
                    sectionCard.className = 'card mb-3';

                    var sectionHeader = document.createElement('div');
                    sectionHeader.className = 'card-header py-2';
                    sectionHeader.innerHTML = '<strong>' + escapeHtml(textOrDash(section.title || section.section_id)) + '</strong>';
                    sectionCard.appendChild(sectionHeader);

                    var sectionBody = document.createElement('div');
                    sectionBody.className = 'card-body';

                    if (section.description) {
                        var sectionDescription = document.createElement('p');
                        sectionDescription.className = 'text-muted small';
                        sectionDescription.textContent = section.description;
                        sectionBody.appendChild(sectionDescription);
                    }

                    var fields = Array.isArray(section.fields) ? section.fields : [];
                    if (!fields.length) {
                        var noFields = document.createElement('div');
                        noFields.className = 'text-muted';
                        noFields.textContent = 'No fields in this section.';
                        sectionBody.appendChild(noFields);
                    }

                    for (var f = 0; f < fields.length; f++) {
                        var field = fields[f] || {};
                        if (!field.name) {
                            continue;
                        }

                        var configValue = resolveFieldConfigValue(scope, field);
                        var nativeValue = configValueToNative(configValue);

                        var wrapper = document.createElement('div');
                        wrapper.className = 'mb-3 plugin-field';
                        wrapper.dataset.scope = scope;
                        wrapper.dataset.fieldName = field.name;
                        wrapper.dataset.fieldType = normalizeEnum(field.field_type);
                        wrapper.dataset.widget = normalizeEnum(field.widget);
                        wrapper.dataset.visibleWhenField = field.visible_when_field || '';
                        wrapper.dataset.visibleWhenEquals = JSON.stringify(field.visible_when_equals || null);

                        var label = document.createElement('label');
                        label.className = 'form-label';
                        label.setAttribute('for', toInputID(scope, field.name));
                        label.innerHTML = escapeHtml(field.label || field.name) + (field.required ? ' <span class="text-danger">*</span>' : '');
                        wrapper.appendChild(label);

                        var input = renderFieldInput(scope, field, nativeValue);
                        wrapper.appendChild(input);

                        if (field.description || field.help_text) {
                            var help = document.createElement('div');
                            help.className = 'form-text';
                            help.textContent = field.help_text || field.description || '';
                            wrapper.appendChild(help);
                        }

                        sectionBody.appendChild(wrapper);
                    }

                    sectionCard.appendChild(sectionBody);
                    root.appendChild(sectionCard);
                }

                root.addEventListener('change', function() {
                    applyVisibility(scope);
                });
                root.addEventListener('input', function() {
                    applyVisibility(scope);
                });

                applyVisibility(scope);
            }

            function readRawFieldValue(scope, fieldName) {
                var input = document.getElementById(toInputID(scope, fieldName));
                if (!input) {
                    return null;
                }
                if (input.tagName === 'SELECT' && input.multiple) {
                    return getSelectValueArray(input);
                }
                if (input.type === 'checkbox') {
                    return !!input.checked;
                }
                return input.value;
            }

            function compareVisibleValue(currentValue, expectedValueObject) {
                if (!expectedValueObject) {
                    return true;
                }
                var expectedNative = configValueToNative(expectedValueObject);
                if (Array.isArray(expectedNative)) {
                    if (!Array.isArray(currentValue)) {
                        return false;
                    }
                    if (expectedNative.length !== currentValue.length) {
                        return false;
                    }
                    for (var i = 0; i < expectedNative.length; i++) {
                        if (String(expectedNative[i]) !== String(currentValue[i])) {
                            return false;
                        }
                    }
                    return true;
                }
                return String(currentValue) === String(expectedNative);
            }

            function applyVisibility(scope) {
                var fields = document.querySelectorAll('.plugin-field[data-scope="' + scope + '"]');
                for (var i = 0; i < fields.length; i++) {
                    var wrapper = fields[i];
                    var dependsOn = wrapper.dataset.visibleWhenField;
                    if (!dependsOn) {
                        wrapper.classList.remove('plugin-field-hidden');
                        continue;
                    }

                    var expectedRaw = null;
                    try {
                        expectedRaw = JSON.parse(wrapper.dataset.visibleWhenEquals || 'null');
                    } catch (e) {
                        expectedRaw = null;
                    }
                    var current = readRawFieldValue(scope, dependsOn);
                    var visible = compareVisibleValue(current, expectedRaw);
                    if (visible) {
                        wrapper.classList.remove('plugin-field-hidden');
                    } else {
                        wrapper.classList.add('plugin-field-hidden');
                    }
                }
            }

            function collectConfigValues(scope, form) {
                var out = {};
                if (!form || !Array.isArray(form.sections)) {
                    return out;
                }

                for (var s = 0; s < form.sections.length; s++) {
                    var section = form.sections[s] || {};
                    var fields = Array.isArray(section.fields) ? section.fields : [];
                    for (var f = 0; f < fields.length; f++) {
                        var field = fields[f] || {};
                        if (!field.name) {
                            continue;
                        }

                        var wrapper = document.querySelector('.plugin-field[data-scope="' + scope + '"][data-field-name="' + field.name + '"]');
                        if (wrapper && wrapper.classList.contains('plugin-field-hidden')) {
                            continue;
                        }

                        var input = document.getElementById(toInputID(scope, field.name));
                        if (!input) {
                            continue;
                        }

                        var rawValue;
                        if (input.tagName === 'SELECT' && input.multiple) {
                            rawValue = getSelectValueArray(input);
                        } else if (input.type === 'checkbox') {
                            rawValue = !!input.checked;
                        } else {
                            rawValue = input.value;
                        }

                        if (field.required) {
                            var missing = false;
                            if (input.type === 'checkbox') {
                                missing = false;
                            } else if (Array.isArray(rawValue)) {
                                missing = rawValue.length === 0;
                            } else {
                                missing = String(rawValue || '').trim() === '';
                            }
                            if (missing) {
                                throw new Error('Missing required field: ' + (field.label || field.name));
                            }
                        }

                        var converted = nativeToConfigValue(rawValue, field.field_type, field.widget, field);
                        if (converted !== null) {
                            out[field.name] = converted;
                        }
                    }
                }

                return out;
            }

            function renderDescriptorSummary() {
                var summary = document.getElementById('plugin-descriptor-summary');
                if (!state.descriptor) {
                    summary.innerHTML = 'No descriptor loaded.';
                    return;
                }

                var descriptor = state.descriptor;
                var html = '';
                html += '<div><strong>' + escapeHtml(textOrDash(descriptor.display_name || descriptor.job_type)) + '</strong></div>';
                html += '<div><small>Job Type: ' + escapeHtml(textOrDash(descriptor.job_type)) + '</small></div>';
                html += '<div><small>Descriptor Version: ' + escapeHtml(textOrDash(descriptor.descriptor_version)) + '</small></div>';
                if (descriptor.description) {
                    html += '<div class="mt-1">' + escapeHtml(descriptor.description) + '</div>';
                }
                summary.innerHTML = html;
            }

            function fillAdminSettings() {
                var runtimeConfig = (state.config && state.config.admin_runtime) ? state.config.admin_runtime : {};
                var defaults = (state.descriptor && state.descriptor.admin_runtime_defaults) ? state.descriptor.admin_runtime_defaults : {};

                function pickNumber(key) {
                    if (runtimeConfig && runtimeConfig[key] !== undefined && runtimeConfig[key] !== null) {
                        return runtimeConfig[key];
                    }
                    if (defaults && defaults[key] !== undefined && defaults[key] !== null) {
                        return defaults[key];
                    }
                    return 0;
                }

                function pickBool(key) {
                    if (runtimeConfig && runtimeConfig[key] !== undefined && runtimeConfig[key] !== null) {
                        return !!runtimeConfig[key];
                    }
                    if (defaults && defaults[key] !== undefined && defaults[key] !== null) {
                        return !!defaults[key];
                    }
                    return true;
                }

                document.getElementById('plugin-admin-enabled').checked = pickBool('enabled');
                document.getElementById('plugin-admin-detection-interval').value = String(pickNumber('detection_interval_minutes'));
                document.getElementById('plugin-admin-detection-timeout').value = String(pickNumber('detection_timeout_seconds'));
                document.getElementById('plugin-admin-execution-timeout').value = String(pickNumber('execution_timeout_seconds'));
                document.getElementById('plugin-admin-max-runtime').value = String(pickNumber('job_type_max_runtime_seconds'));
                document.getElementById('plugin-admin-max-results').value = String(pickNumber('max_jobs_per_detection'));
                document.getElementById('plugin-admin-global-exec').value = String(pickNumber('global_execution_concurrency'));
                document.getElementById('plugin-admin-per-worker-exec').value = String(pickNumber('per_worker_execution_concurrency'));
                document.getElementById('plugin-admin-retry-limit').value = String(pickNumber('retry_limit'));
                document.getElementById('plugin-admin-retry-backoff').value = String(pickNumber('retry_backoff_seconds'));
            }

            function collectAdminSettings() {
                function getInt(id) {
                    var raw = String(document.getElementById(id).value || '').trim();
                    if (!raw) {
                        return 0;
                    }
                    var parsed = parseInt(raw, 10);
                    if (Number.isNaN(parsed) || parsed < 0) {
                        throw new Error('Invalid number for ' + id);
                    }
                    return parsed;
                }

                return {
                    enabled: !!document.getElementById('plugin-admin-enabled').checked,
                    detection_interval_minutes: getInt('plugin-admin-detection-interval'),
                    detection_timeout_seconds: getInt('plugin-admin-detection-timeout'),
                    execution_timeout_seconds: getInt('plugin-admin-execution-timeout'),
                    job_type_max_runtime_seconds: getInt('plugin-admin-max-runtime'),
                    max_jobs_per_detection: getInt('plugin-admin-max-results'),
                    global_execution_concurrency: getInt('plugin-admin-global-exec'),
                    per_worker_execution_concurrency: getInt('plugin-admin-per-worker-exec'),
                    retry_limit: getInt('plugin-admin-retry-limit'),
                    retry_backoff_seconds: getInt('plugin-admin-retry-backoff'),
                };
            }

            function renderRunHistory(history) {
                var successBody = document.getElementById('plugin-runs-success-body');
                var errorBody = document.getElementById('plugin-runs-error-body');

                var successRuns = (history && Array.isArray(history.successful_runs)) ? history.successful_runs : [];
                var errorRuns = (history && Array.isArray(history.error_runs)) ? history.error_runs : [];

                if (!successRuns.length) {
                    successBody.innerHTML = '<tr><td colspan="4" class="text-muted">No successful runs</td></tr>';
                } else {
                    var successRows = '';
                    for (var i = 0; i < successRuns.length; i++) {
                        var run = successRuns[i] || {};
                        successRows += '<tr>' +
                            '<td><small>' + escapeHtml(parseTime(run.completed_at) || '-') + '</small></td>' +
                            '<td>' + renderJobLink(run.job_id) + '</td>' +
                            '<td><small>' + escapeHtml(textOrDash(run.worker_id)) + '</small></td>' +
                            '<td><small>' + escapeHtml(formatDurationMs(run.duration_ms)) + '</small></td>' +
                            '</tr>';
                    }
                    successBody.innerHTML = successRows;
                }

                if (!errorRuns.length) {
                    errorBody.innerHTML = '<tr><td colspan="4" class="text-muted">No error runs</td></tr>';
                } else {
                    var errorRows = '';
                    for (var j = 0; j < errorRuns.length; j++) {
                        var errorRun = errorRuns[j] || {};
                        errorRows += '<tr>' +
                            '<td><small>' + escapeHtml(parseTime(errorRun.completed_at) || '-') + '</small></td>' +
                            '<td>' + renderJobLink(errorRun.job_id) + '</td>' +
                            '<td><small>' + escapeHtml(textOrDash(errorRun.worker_id)) + '</small></td>' +
                            '<td><small class="text-danger">' + escapeHtml(textOrDash(errorRun.message)) + '</small></td>' +
                            '</tr>';
                    }
                    errorBody.innerHTML = errorRows;
                }
            }

            function renderDetectionResult(data) {
                var root = document.getElementById('plugin-detection-results');
                if (!root) {
                    return;
                }

                function normalizeProposals(payload) {
                    if (!payload || typeof payload !== 'object') {
                        return [];
                    }
                    if (Array.isArray(payload.proposals)) {
                        return payload.proposals;
                    }
                    if (payload.proposals && typeof payload.proposals === 'object') {
                        return Object.keys(payload.proposals).map(function(key) {
                            return payload.proposals[key];
                        }).filter(function(item) {
                            return !!item;
                        });
                    }
                    return [];
                }

                function proposalID(proposal) {
                    return proposal.proposal_id || proposal.proposalId || proposal.id || '';
                }

                function proposalSummary(proposal) {
                    return proposal.summary || proposal.title || proposalID(proposal) || 'Proposal';
                }

                function proposalDetail(proposal) {
                    return proposal.detail || proposal.reason || proposal.message || '-';
                }

                function normalizeActivities(payload) {
                    if (!payload || typeof payload !== 'object') {
                        return [];
                    }
                    if (Array.isArray(payload.activities)) {
                        return payload.activities;
                    }
                    return [];
                }

                function encodeDetails(details) {
                    if (!details || typeof details !== 'object') {
                        return '';
                    }
                    var text = '';
                    try {
                        text = JSON.stringify(details);
                    } catch (e) {
                        text = '';
                    }
                    if (!text) {
                        return '';
                    }
                    if (text.length > 360) {
                        text = text.slice(0, 360) + '...';
                    }
                    return text;
                }

                if (!data) {
                    root.innerHTML = '<div class="text-muted">No results.</div>';
                    return;
                }

                var proposals = normalizeProposals(data);
                var activities = normalizeActivities(data);
                var responseCount = Number(data.count || 0);
                if (!Number.isFinite(responseCount) || responseCount < 0) {
                    responseCount = proposals.length;
                }
                var requestID = data.request_id || data.requestId || '';
                var detectorWorkerID = data.detector_worker_id || data.detectorWorkerId || '';
                var totalProposals = Number(data.total_proposals || 0);
                if (!Number.isFinite(totalProposals) || totalProposals < 0) {
                    totalProposals = responseCount;
                }

                var html = '';
                html += '<div class="mb-2"><strong>Detection Run</strong></div>';
                if (requestID) {
                    html += '<div><small>request_id: ' + escapeHtml(String(requestID)) + '</small></div>';
                }
                if (detectorWorkerID) {
                    html += '<div><small>detector: ' + escapeHtml(String(detectorWorkerID)) + '</small></div>';
                }
                html += '<div><small>proposals: ' + escapeHtml(String(responseCount)) + ' / total: ' + escapeHtml(String(totalProposals)) + '</small></div>';
                if (data.error) {
                    html += '<div class="mt-1 text-danger"><small>' + escapeHtml(String(data.error)) + '</small></div>';
                }

                if (!proposals.length) {
                    html += '<div class="mt-2 text-muted">No proposals returned.</div>';
                } else {
                    html += '<div class="mt-2 mb-1"><strong>' + escapeHtml(String(proposals.length)) + '</strong> proposal(s)</div>';
                    for (var i = 0; i < proposals.length; i++) {
                        var proposal = proposals[i] || {};
                        var pID = proposalID(proposal);
                        var pSummary = proposalSummary(proposal);
                        var pDetail = proposalDetail(proposal);
                        var pPriority = proposal.priority;
                        if (pPriority === null || pPriority === undefined || pPriority === '') {
                            pPriority = '-';
                        }
                        html += '<div class="plugin-detection-item">' +
                            '<div class="fw-semibold">' + escapeHtml(textOrDash(pSummary)) + '</div>' +
                            '<div><small>proposal_id: ' + escapeHtml(textOrDash(pID)) + '</small></div>' +
                            '<div><small>priority: ' + escapeHtml(textOrDash(pPriority)) + '</small></div>' +
                            '<div><small>detail: ' + escapeHtml(textOrDash(pDetail)) + '</small></div>' +
                            '</div>';
                    }
                }

                if (activities.length) {
                    html += '<hr class="my-2"/>';
                    html += '<div class="mb-2"><strong>Detection Process</strong></div>';
                    for (var j = 0; j < activities.length; j++) {
                        var activity = activities[j] || {};
                        var activityStage = activity.stage || '-';
                        var activitySource = activity.source || '-';
                        var activityMessage = activity.message || '-';
                        var activityTime = parseTime(activity.occurred_at) || '-';
                        var detailsText = encodeDetails(activity.details);
                        html += '<div class="plugin-detection-item">' +
                            '<div class="fw-semibold">' + escapeHtml(textOrDash(activityStage)) + '</div>' +
                            '<div><small>source: ' + escapeHtml(textOrDash(activitySource)) + ' | at: ' + escapeHtml(activityTime) + '</small></div>' +
                            '<div><small>' + escapeHtml(textOrDash(activityMessage)) + '</small></div>';
                        if (detailsText) {
                            html += '<div><small class="text-muted">details: ' + escapeHtml(detailsText) + '</small></div>';
                        }
                        html += '</div>';
                    }
                }

                root.innerHTML = html;
            }

            function getSelectedJobType() {
                return String(state.selectedJobType || '').trim();
            }

            function resetJobTypePanels() {
                state.loadedJobType = '';
                state.descriptor = null;
                state.config = null;
                document.getElementById('plugin-descriptor-summary').textContent = 'No descriptor loaded.';
                document.getElementById('plugin-admin-config-form').innerHTML = '<div class="text-muted">No admin form loaded.</div>';
                document.getElementById('plugin-worker-config-form').innerHTML = '<div class="text-muted">No worker form loaded.</div>';
                document.getElementById('plugin-config-updated-at').textContent = 'Not loaded';
                renderRunHistory(null);
                renderDetectionResult(null);
            }

            async function loadDescriptorAndConfig(jobType, forceRefresh) {
                if (!jobType) {
                    return;
                }

                state.selectedJobType = jobType;
                renderNavigationState();

                var summary = document.getElementById('plugin-descriptor-summary');
                summary.textContent = 'Loading descriptor and config...';

                try {
                    if (forceRefresh) {
                        var refreshURL = '/api/plugin/job-types/' + encodePath(jobType) + '/schema?force_refresh=true';
                        state.descriptor = await pluginRequest('POST', refreshURL, null);
                    } else {
                        try {
                            state.descriptor = await pluginRequest('GET', '/api/plugin/job-types/' + encodePath(jobType) + '/descriptor');
                        } catch (descriptorLoadError) {
                            state.descriptor = await pluginRequest('POST', '/api/plugin/job-types/' + encodePath(jobType) + '/schema', null);
                        }
                    }
                } catch (schemaError) {
                    state.loadedJobType = '';
                    state.descriptor = null;
                    summary.innerHTML = '<span class="text-danger">Failed to load descriptor: ' + escapeHtml(schemaError.message) + '</span>';
                    document.getElementById('plugin-admin-config-form').innerHTML = '<div class="text-muted">No admin form loaded.</div>';
                    document.getElementById('plugin-worker-config-form').innerHTML = '<div class="text-muted">No worker form loaded.</div>';
                    throw schemaError;
                }

                try {
                    state.config = await pluginRequest('GET', '/api/plugin/job-types/' + encodePath(jobType) + '/config');
                } catch (configError) {
                    state.config = null;
                    notify('Failed to load config: ' + configError.message, 'error');
                }

                renderDescriptorSummary();
                fillAdminSettings();

                if (state.descriptor) {
                    renderConfigForm('admin', 'plugin-admin-config-form', state.descriptor.admin_config_form || {});
                    renderConfigForm('worker', 'plugin-worker-config-form', state.descriptor.worker_config_form || {});
                }

                if (state.config && state.config.updated_at) {
                    document.getElementById('plugin-config-updated-at').textContent = 'Updated: ' + (parseTime(state.config.updated_at) || state.config.updated_at);
                } else {
                    document.getElementById('plugin-config-updated-at').textContent = 'Not saved yet';
                }
                state.loadedJobType = jobType;

                await loadRunHistory(jobType);

                if (state.lastDetectionByJobType && state.lastDetectionByJobType[jobType]) {
                    renderDetectionResult(state.lastDetectionByJobType[jobType]);
                } else {
                    renderDetectionResult(null);
                }
            }

            async function loadRunHistory(jobType) {
                if (!jobType) {
                    renderRunHistory(null);
                    return;
                }
                try {
                    var history = await pluginRequest('GET', '/api/plugin/job-types/' + encodePath(jobType) + '/runs');
                    renderRunHistory(history);
                } catch (e) {
                    renderRunHistory(null);
                    notify('Failed to load run history: ' + e.message, 'error');
                }
            }

            async function saveConfig() {
                var jobType = state.selectedJobType || getSelectedJobType();
                if (!jobType) {
                    notify('Select a job type first.', 'error');
                    return;
                }
                if (!state.descriptor) {
                    notify('Load descriptor before saving config.', 'error');
                    return;
                }

                var payload;
                try {
                    payload = {
                        job_type: jobType,
                        descriptor_version: state.descriptor.descriptor_version || 0,
                        admin_runtime: collectAdminSettings(),
                        admin_config_values: collectConfigValues('admin', state.descriptor.admin_config_form || {}),
                        worker_config_values: collectConfigValues('worker', state.descriptor.worker_config_form || {}),
                    };
                } catch (err) {
                    notify(err.message, 'error');
                    return;
                }

                try {
                    state.config = await pluginRequest('PUT', '/api/plugin/job-types/' + encodePath(jobType) + '/config', payload);
                    document.getElementById('plugin-config-updated-at').textContent = 'Updated: ' + (parseTime(state.config.updated_at) || state.config.updated_at || 'just now');
                    notify('Config saved for ' + jobType, 'success');
                } catch (e) {
                    notify('Failed to save config: ' + e.message, 'error');
                }
            }

            function getMaxResults() {
                var raw = String(document.getElementById('plugin-admin-max-results').value || '').trim();
                if (!raw) {
                    return 0;
                }
                var parsed = parseInt(raw, 10);
                if (Number.isNaN(parsed) || parsed < 0) {
                    return 0;
                }
                return parsed;
            }

            async function runDetection() {
                var jobType = state.selectedJobType || getSelectedJobType();
                if (!jobType) {
                    notify('Select a job type first.', 'error');
                    return;
                }

                try {
                    var data = await pluginRequest('POST', '/api/plugin/job-types/' + encodePath(jobType) + '/detect', {
                        max_results: getMaxResults(),
                    });
                    state.lastDetectionByJobType[jobType] = data;
                    renderDetectionResult(data);
                } catch (e) {
                    if (e && e.responseData) {
                        state.lastDetectionByJobType[jobType] = e.responseData;
                        renderDetectionResult(e.responseData);
                    }
                    notify('Detection failed: ' + e.message, 'error');
                    return;
                }

                try {
                    await refreshJobsAndActivities();
                } catch (refreshErr) {
                    notify('Detection succeeded, but monitoring refresh failed: ' + refreshErr.message, 'error');
                }
            }

            async function runWorkflow() {
                var jobType = state.selectedJobType || getSelectedJobType();
                if (!jobType) {
                    notify('Select a job type first.', 'error');
                    return;
                }

                try {
                    var data = await pluginRequest('POST', '/api/plugin/job-types/' + encodePath(jobType) + '/run', {
                        max_results: getMaxResults(),
                    });
                    var resultRoot = document.getElementById('plugin-detection-results');
                    resultRoot.innerHTML = '<div class="mb-2"><strong>Workflow completed</strong></div>' +
                        '<div>Detected: <strong>' + escapeHtml(String(data.detected_count || 0)) + '</strong></div>' +
                        '<div>Ready to Execute: <strong>' + escapeHtml(String(data.ready_to_execute_count || 0)) + '</strong></div>' +
                        '<div>Skipped (Already Active): <strong>' + escapeHtml(String(data.skipped_active_count || 0)) + '</strong></div>' +
                        '<div>Executed: <strong>' + escapeHtml(String(data.executed_count || 0)) + '</strong></div>' +
                        '<div class="text-success">Success: ' + escapeHtml(String(data.success_count || 0)) + '</div>' +
                        '<div class="text-danger">Errors: ' + escapeHtml(String(data.error_count || 0)) + '</div>';
                    await loadRunHistory(jobType);
                    await refreshJobsAndActivities();
                } catch (e) {
                    notify('Workflow run failed: ' + e.message, 'error');
                }
            }

            async function refreshJobsAndActivities() {
                var executionStateFilter = document.getElementById('plugin-monitor-job-state-filter');

                state.monitorExecutionJobState = executionStateFilter ? String(executionStateFilter.value || '').trim() : '';

                var allJobsPromise = pluginRequest('GET', appendLaneParam('/api/plugin/jobs?limit=500'));
                var allActivitiesPromise = pluginRequest('GET', appendLaneParam('/api/plugin/activities?limit=500'));
                var schedulerPromise = pluginRequest('GET', appendLaneParam('/api/plugin/scheduler-states'));
                var schedulerStatusPromise = pluginRequest('GET', appendLaneParam('/api/plugin/scheduler-status'));

                var allJobs = await allJobsPromise;
                var allActivities = await allActivitiesPromise;
                var schedulerStates = await schedulerPromise;
                var schedulerStatus = null;
                try {
                    schedulerStatus = await schedulerStatusPromise;
                } catch (e) {
                    schedulerStatus = null;
                }

                state.jobs = Array.isArray(allJobs) ? allJobs : [];
                state.activities = Array.isArray(allActivities) ? allActivities : [];
                state.allJobs = state.jobs;
                state.allActivities = state.activities;
                state.schedulerStates = Array.isArray(schedulerStates) ? schedulerStates : [];
                state.schedulerStatus = schedulerStatus && schedulerStatus.scheduler ? schedulerStatus.scheduler : null;
                renderQueueJobs();
                renderDetectionJobs();
                renderExecutionJobs();
                renderExecutionActivities();
                renderSchedulerStates();
                renderSchedulerStatus();
                renderStatus();
                renderJobTypeSummary();
            }

            async function refreshAll() {
                try {
                    var previousSelectedJobType = state.selectedJobType;

                    var workers = await pluginRequest('GET', appendLaneParam('/api/plugin/workers'));
                    state.workers = Array.isArray(workers) ? workers : [];
                    renderWorkers();

                    var jobTypes = await pluginRequest('GET', appendLaneParam('/api/plugin/job-types'));
                    state.jobTypes = Array.isArray(jobTypes) ? jobTypes : [];
                    applyInitialNavigation();
                    ensureActiveNavigation();
                    renderTopTabs();
                    renderNavigationState();

                    if (!state.selectedJobType) {
                        resetJobTypePanels();
                    } else if (state.loadedJobType !== state.selectedJobType || previousSelectedJobType !== state.selectedJobType) {
                        try {
                            await loadDescriptorAndConfig(state.selectedJobType, false);
                        } catch (loadError) {
                            // Already rendered in UI.
                        }
                    }

                    await refreshJobsAndActivities();
                } catch (e) {
                    notify('Refresh failed: ' + e.message, 'error');
                }
            }

            function bindActions() {
                var monitorStateFilter = document.getElementById('plugin-monitor-job-state-filter');
                if (monitorStateFilter) {
                    monitorStateFilter.addEventListener('change', function() {
                        state.monitorExecutionJobState = String(monitorStateFilter.value || '').trim();
                        renderExecutionJobs();
                    });
                }

                var expireBtn = document.getElementById('plugin-expire-job-btn');
                if (expireBtn) {
                    expireBtn.addEventListener('click', function() {
                        var jobID = String(expireBtn.getAttribute('data-job-id') || '').trim();
                        if (!jobID) {
                            return;
                        }
                        expireJob(jobID);
                    });
                }

                document.getElementById('plugin-refresh-all-btn').addEventListener('click', function() {
                    refreshAll();
                });

                document.getElementById('plugin-refresh-schema-btn').addEventListener('click', async function() {
                    var jobType = getSelectedJobType();
                    if (!jobType) {
                        notify('Select a job type first.', 'error');
                        return;
                    }
                    try {
                        await loadDescriptorAndConfig(jobType, true);
                        notify('Schema refreshed for ' + jobType, 'success');
                    } catch (e) {
                        notify('Schema refresh failed: ' + e.message, 'error');
                    }
                });

                document.getElementById('plugin-save-config-btn').addEventListener('click', function() {
                    saveConfig();
                });

                document.getElementById('plugin-trigger-detection-btn').addEventListener('click', function() {
                    runDetection();
                });

                document.getElementById('plugin-run-workflow-btn').addEventListener('click', function() {
                    runWorkflow();
                });

                page.addEventListener('click', async function(event) {
                    var target = event.target;
                    if (!target) {
                        return;
                    }

                    var topTab = target.closest('[data-plugin-top-tab]');
                    if (topTab) {
                        event.preventDefault();
                        var topTabKey = String(topTab.getAttribute('data-plugin-top-tab') || '').trim();
                        if (!topTabKey) {
                            return;
                        }
                        if (topTabKey === 'overview') {
                            state.activeTopTab = 'overview';
                            renderNavigationState();
                            updateURL(false);
                            return;
                        }

                        var jobType = parseJobTypeFromTopTab(topTabKey);
                        if (!jobType) {
                            return;
                        }
                        state.activeTopTab = topTabKey;
                        state.selectedJobType = jobType;
                        ensureActiveNavigation();
                        renderNavigationState();
                        updateURL(false);
                        if (state.loadedJobType !== jobType) {
                            try {
                                await loadDescriptorAndConfig(jobType, false);
                            } catch (e) {
                                // Already rendered in UI.
                            }
                        } else {
                            if (state.lastDetectionByJobType && state.lastDetectionByJobType[jobType]) {
                                renderDetectionResult(state.lastDetectionByJobType[jobType]);
                            } else {
                                renderDetectionResult(null);
                            }
                            await loadRunHistory(jobType);
                        }
                        renderQueueJobs();
                        renderDetectionJobs();
                        renderExecutionJobs();
                        renderExecutionActivities();
                        return;
                    }

                    var subTab = target.closest('[data-plugin-subtab]');
                    if (subTab) {
                        event.preventDefault();
                        var subTabKey = normalizeSubTab(subTab.getAttribute('data-plugin-subtab'));
                        state.activeSubTab = subTabKey;
                        renderNavigationState();
                        updateURL(false);
                        return;
                    }

                    var trigger = target.closest('.plugin-job-link');
                    if (!trigger) {
                        return;
                    }
                    event.preventDefault();
                    var jobID = trigger.getAttribute('data-job-id');
                    if (!jobID) {
                        return;
                    }
                    openJobDetail(jobID);
                });
            }

            async function init() {
                bindActions();
                renderTopTabs();
                ensureActiveNavigation();
                renderNavigationState();
                await refreshAll();

                // Set the initial browser history state to match the current view
                updateURL(true);

                state.refreshTimer = setInterval(function() {
                    refreshAll();
                }, 3000);
            }

            window.addEventListener('popstate', async function(event) {
                var s = event.state;
                if (!s || !s.pluginTopTab) {
                    // No plugin state — treat as overview
                    state.activeTopTab = 'overview';
                    renderNavigationState();
                    return;
                }
                state.activeTopTab = String(s.pluginTopTab || 'overview');
                state.activeSubTab = normalizeSubTab(s.pluginSubTab);
                var jobType = String(s.pluginJob || '').trim();
                if (jobType) {
                    state.selectedJobType = jobType;
                }
                ensureActiveNavigation();
                renderNavigationState();
                // If a job type is selected and not loaded yet, load it
                if (state.selectedJobType && state.loadedJobType !== state.selectedJobType) {
                    try {
                        await loadDescriptorAndConfig(state.selectedJobType, false);
                    } catch (e) {
                        console.error('Failed to load data on popstate navigation:', e);
                    }
                }
                renderQueueJobs();
                renderDetectionJobs();
                renderExecutionJobs();
                renderExecutionActivities();
            });

            window.addEventListener('beforeunload', function() {
                if (state.refreshTimer) {
                    clearInterval(state.refreshTimer);
                    state.refreshTimer = null;
                }
            });

            init();
        })();
        </script>
}
