(() => { const actions = [ ['P-01', 'act.p-01.01', '进入租户/账务/题库/审计', 'command', 'native', 'nav', '[data-nav="tenants"],[data-nav="billing"],[data-nav="bank"],[data-nav="audit"]', 'PlatformAdminOverviewController_overview', 'allow'], ['P-01', 'act.p-01.02', '确认/解决告警', 'command', 'native', 'mutation', '[data-alert-detail],[data-action="transition-alert"]', 'PlatformAdminAuditController_alerts', 'allow'], ['P-01', 'act.p-01.03', '导出审计', 'async', 'native', 'task', '[data-action="export-audit"]', 'PlatformAdminAuditController_logs', 'allow'], ['P-01', 'act.p-01.04', '刷新', 'command', 'native', 'read', '[data-action="refresh"]', 'PlatformAdminOverviewController_overview', 'allow'], ['P-02', 'act.p-02.01', '搜索', 'command', 'native', 'read', '#tenantSearch,[data-action="apply-tenant-query"]', 'PlatformAdminTenantsController_list', 'allow'], ['P-02', 'act.p-02.02', '创建租户', 'command', 'native', 'mutation', '[data-action="create-tenant"],[form="createTenantForm"]', 'PlatformAdminTenantsController_create', 'block'], ['P-02', 'act.p-02.03', '打开详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminTenantsController_list', 'allow'], ['P-02', 'act.p-02.04', '准备暂停/恢复', 'destructive', 'native', 'mutation', '[data-action="prepare-tenant-status"],[form="tenantStatusForm"]', 'PlatformAdminTenantsController_status', 'block'], ['P-02', 'act.p-02.05', '去账务', 'command', 'native', 'nav', '[data-action="tenant-to-billing"]', 'PlatformAdminBillingController_invoices', 'allow'], ['P-03', 'act.p-03.01', '修改状态', 'command', 'native', 'mutation', '[data-action="prepare-tenant-status"],[form="tenantStatusForm"]', 'PlatformAdminTenantsController_status', 'block'], ['P-03', 'act.p-03.02', '编辑账务资料', 'command', 'native', 'nav', '[data-action="edit-billing-profile"]', 'PlatformAdminTenantsController_billingProfile', 'block'], ['P-03', 'act.p-03.03', '创建订阅', 'command', 'native', 'mutation', '[data-action="create-subscription-for-tenant"],[form="subscriptionForm"]', 'PlatformAdminBillingController_createSubscription', 'block'], ['P-03', 'act.p-03.04', '查看账单/用量', 'command', 'native', 'nav', '[data-action="tenant-to-billing"],[data-action="tenant-to-usage"]', 'PlatformAdminTenantsController_detail', 'allow'], ['P-03', 'act.p-03.05', '跳转租户门户(只做链接,不冒充登录)', 'command', 'native', 'nav', '[data-action="open-tenant-portal"]', 'PlatformAdminTenantsController_detail', 'allow'], ['P-04', 'act.p-04.01', '编辑', 'command', 'native', 'mutation', '#billingProfileForm', 'PlatformAdminTenantsController_billingProfile', 'block'], ['P-04', 'act.p-04.02', '保存', 'command', 'native', 'mutation', '[form="billingProfileForm"]', 'PlatformAdminTenantsController_billingProfile', 'block'], ['P-04', 'act.p-04.03', '查看关联账单', 'command', 'native', 'nav', '[data-action="billing-profile-to-invoices"]', 'PlatformAdminTenantsController_billingProfile', 'allow'], ['P-05', 'act.p-05.01', '选择套餐', 'command', 'native', 'mutation', '[data-action="select-plan"]', 'PlatformAdminOverviewController_plans', 'block'], ['P-05', 'act.p-05.02', '创建订阅', 'command', 'native', 'mutation', '[data-action="create-subscription"],[form="subscriptionForm"]', 'PlatformAdminBillingController_createSubscription', 'block'], ['P-05', 'act.p-05.03', '进入账单候选', 'command', 'native', 'nav', '[data-action="subscription-to-billing"]', 'PlatformAdminBillingController_createSubscription', 'allow'], ['P-05', 'act.p-05.04', '查看租户详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_createSubscription', 'allow'], ['P-06', 'act.p-06.01', '查询', 'command', 'contract', 'read', '[data-action="apply-invoice-query"]', 'PlatformAdminBillingController_invoices', 'allow'], ['P-06', 'act.p-06.02', '手工创建', 'command', 'native', 'mutation', '[data-action="create-invoice"],[form="invoiceForm"]', 'PlatformAdminBillingController_createInvoice', 'block'], ['P-06', 'act.p-06.03', '预览候选', 'command', 'native', 'read', '[data-action="preview-invoice-candidates"]', 'PlatformAdminBillingController_subscriptionCandidates', 'block'], ['P-06', 'act.p-06.04', '单个生成', 'async', 'contract', 'task', '[data-action="generate-subscription-invoice"]', 'PlatformAdminBillingController_fromSubscription', 'block'], ['P-06', 'act.p-06.05', '批量 dry-run', 'command', 'native', 'read', '[data-action="run-invoice-dry-run"]', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'block'], ['P-06', 'act.p-06.06', '确认生成', 'async', 'native', 'task', '[data-action="confirm-generate-candidates"]', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'block'], ['P-06', 'act.p-06.07', '打开租户', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_invoices', 'allow'], ['P-07', 'act.p-07.01', '记录用量', 'command', 'native', 'mutation', '[data-action="record-usage"],[form="usageForm"]', 'PlatformAdminBillingController_recordUsage', 'block'], ['P-07', 'act.p-07.02', '查询', 'command', 'native', 'read', '#usagePeriodFilter', 'PlatformAdminBillingController_usage', 'allow'], ['P-07', 'act.p-07.03', '预览超额候选', 'command', 'native', 'read', '[data-action="preview-overage"]', 'PlatformAdminBillingController_usageCandidates', 'block'], ['P-07', 'act.p-07.04', 'dry-run', 'command', 'native', 'read', '[data-action="run-overage-dry-run"]', 'PlatformAdminBillingController_fromUsage', 'block'], ['P-07', 'act.p-07.05', '生成超额账单', 'async', 'native', 'task', '[data-action="confirm-overage-invoices"]', 'PlatformAdminBillingController_fromUsage', 'block'], ['P-07', 'act.p-07.06', '跳租户详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_usage', 'allow'], ['P-08', 'act.p-08.01', '确认收款', 'command', 'native', 'mutation', '[data-action="confirm-payment"],[form="paymentForm"]', 'PlatformAdminBillingController_confirmPayment', 'block'], ['P-08', 'act.p-08.02', '预览逾期', 'command', 'native', 'read', '[data-action="preview-overdue"]', 'PlatformAdminBillingController_processOverdue', 'block'], ['P-08', 'act.p-08.03', '生成催缴', 'async', 'native', 'task', '[data-action="confirm-overdue-process"],[data-action="generate-reminder"]', 'PlatformAdminBillingController_processOverdue', 'block'], ['P-08', 'act.p-08.04', '查询提醒', 'command', 'native', 'read', '[data-billing-tab="reminders"]', 'PlatformAdminBillingController_reminders', 'allow'], ['P-08', 'act.p-08.05', '新增/编辑/启停渠道', 'command', 'native', 'mutation', '[data-action="new-dunning-channel"],[data-action="edit-dunning-channel"],[data-action="toggle-dunning-channel"]', 'PlatformAdminDunningChannelsController_upsertChannel', 'block'], ['P-08', 'act.p-08.06', '查看通知事件', 'command', 'contract', 'read', '[data-notification-detail]', 'PlatformAdminDunningEventsController_events', 'allow'], ['P-09', 'act.p-09.01', '搜索', 'command', 'contract', 'read', '[data-action="apply-bank-search"]', 'PlatformAdminQuestionBanksController_banks', 'allow'], ['P-09', 'act.p-09.02', '含租户库切换', 'command', 'native', 'read', '#includeTenantBanks', 'PlatformAdminQuestionBanksController_banks', 'allow'], ['P-09', 'act.p-09.03', '新建/编辑/禁用授权', 'destructive', 'native', 'mutation', '[data-action="new-grant"],[data-action="edit-grant"],[data-action="toggle-grant"]', 'PlatformAdminQuestionBanksController_upsertGrant', 'block'], ['P-09', 'act.p-09.04', '选择题库', 'command', 'native', 'read', '[data-bank-select]', 'PlatformAdminQuestionBanksController_banks', 'allow'], ['P-09', 'act.p-09.05', '查看租户采用/同步', 'async', 'contract', 'task', '[data-action="preview-bank-sync"]', 'PlatformAdminQuestionBanksController_syncStatus', 'allow'], ['P-10', 'act.p-10.01', '新建/编辑', 'command', 'native', 'mutation', '[data-action="new-staff"],[data-action="edit-staff"]', 'PlatformAdminOverviewController_upsertStaff', 'block'], ['P-10', 'act.p-10.02', '全选/分组授权', 'command', 'native', 'mutation', '[data-action="select-permission-group"]', 'PlatformAdminOverviewController_permissions', 'block'], ['P-10', 'act.p-10.03', '启用/禁用', 'destructive', 'native', 'mutation', '[data-action="toggle-staff"]', 'PlatformAdminOverviewController_updateStaffStatus', 'block'], ['P-10', 'act.p-10.04', '禁用时撤销会话', 'destructive', 'native', 'audit', '[data-action="execute-staff-disable"]', 'PlatformAdminOverviewController_updateStaffStatus', 'block'], ['P-10', 'act.p-10.05', '清空表单', 'command', 'contract', 'mutation', '[data-action="clear-staff-form"]', 'PlatformAdminOverviewController_upsertStaff', 'block'], ['P-11', 'act.p-11.01', '筛选', 'command', 'native', 'read', '#auditSearch,#auditRangeFilter,[data-audit-severity]', 'PlatformAdminAuditController_logs', 'allow'], ['P-11', 'act.p-11.02', '查看详情', 'command', 'native', 'read', '[data-audit-detail]', 'PlatformAdminAuditController_logs', 'allow'], ['P-11', 'act.p-11.03', '导出 CSV/JSON', 'async', 'native', 'task', '[data-action="export-audit"]', 'PlatformAdminAuditController_exportLogs', 'allow'], ['P-11', 'act.p-11.04', '复制 ID', 'command', 'native', 'read', '[data-copy]', 'PlatformAdminAuditController_logs', 'allow'], ['P-11', 'act.p-11.05', '跳目标对象', 'command', 'native', 'nav', '[data-action="jump-audit-target"],[data-action="jump-related-alert"]', 'PlatformAdminAuditController_logs', 'allow'], ['P-12', 'act.p-12.01', '确认/解决告警', 'command', 'native', 'mutation', '[data-action="transition-alert"]', 'PlatformAdminAuditController_updateAlert', 'allow'], ['P-12', 'act.p-12.02', '查看证据', 'command', 'native', 'read', '[data-alert-detail]', 'PlatformAdminAuditController_alerts', 'allow'], ['P-12', 'act.p-12.03', '新建/编辑/启停通知渠道', 'command', 'native', 'mutation', '[data-action="new-audit-channel"],[data-action="edit-audit-channel"],[data-action="toggle-audit-channel"]', 'PlatformAdminAuditController_upsertChannel', 'block'], ['P-12', 'act.p-12.04', '查看失败事件', 'command', 'contract', 'read', '[data-notification-detail]', 'PlatformAdminAuditController_events', 'allow'], ].map(([pageId, id, label, kind, mode, effect, selector, operationId, mobile]) => ({ pageId, id, label, kind, mode, effect, selector, operationIds: [operationId], mobile, destructive: kind === 'destructive', implemented: true })); const operationRows = [ ['P-01', 'PlatformAdminOverviewController_overview', 'GET', '/api/platform-admin/overview'], ['P-01', 'PlatformAdminAuditController_alerts', 'GET', '/api/platform-admin/audit-alerts'], ['P-01', 'PlatformAdminAuditController_logs', 'GET', '/api/platform-admin/audit-logs'], ['P-02', 'PlatformAdminTenantsController_list', 'GET', '/api/platform-admin/tenants'], ['P-02', 'PlatformAdminTenantsController_create', 'POST', '/api/platform-admin/tenants'], ['P-03', 'PlatformAdminTenantsController_detail', 'GET', '/api/platform-admin/tenants/detail'], ['P-03', 'PlatformAdminTenantsController_status', 'PATCH', '/api/platform-admin/tenants/status'], ['P-03', 'PlatformAdminTenantsController_billingProfile', 'PUT', '/api/platform-admin/tenants/billing-profile'], ['P-03', 'PlatformAdminBillingController_createSubscription', 'POST', '/api/platform-admin/subscriptions'], ['P-04', 'PlatformAdminTenantsController_billingProfile', 'PUT', '/api/platform-admin/tenants/billing-profile'], ['P-05', 'PlatformAdminOverviewController_plans', 'GET', '/api/platform-admin/plans'], ['P-05', 'PlatformAdminBillingController_createSubscription', 'POST', '/api/platform-admin/subscriptions'], ['P-06', 'PlatformAdminBillingController_invoices', 'GET', '/api/platform-admin/invoices'], ['P-06', 'PlatformAdminBillingController_createInvoice', 'POST', '/api/platform-admin/invoices'], ['P-06', 'PlatformAdminBillingController_subscriptionCandidates', 'GET', '/api/platform-admin/invoices/subscription-candidates'], ['P-06', 'PlatformAdminBillingController_fromSubscription', 'POST', '/api/platform-admin/invoices/from-subscription'], ['P-06', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'POST', '/api/platform-admin/invoices/from-subscriptions-batch'], ['P-07', 'PlatformAdminBillingController_usage', 'GET', '/api/platform-admin/usage'], ['P-07', 'PlatformAdminBillingController_recordUsage', 'POST', '/api/platform-admin/usage'], ['P-07', 'PlatformAdminBillingController_usageCandidates', 'GET', '/api/platform-admin/invoices/usage-overage-candidates'], ['P-07', 'PlatformAdminBillingController_fromUsage', 'POST', '/api/platform-admin/invoices/from-usage-overage'], ['P-08', 'PlatformAdminBillingController_confirmPayment', 'POST', '/api/platform-admin/invoices/payments/manual-confirm'], ['P-08', 'PlatformAdminBillingController_processOverdue', 'POST', '/api/platform-admin/invoices/process-overdue'], ['P-08', 'PlatformAdminBillingController_reminders', 'GET', '/api/platform-admin/invoices/reminders'], ['P-08', 'PlatformAdminDunningChannelsController_channels', 'GET', '/api/platform-admin/dunning-notification-channels'], ['P-08', 'PlatformAdminDunningChannelsController_upsertChannel', 'PUT', '/api/platform-admin/dunning-notification-channels'], ['P-08', 'PlatformAdminDunningEventsController_events', 'GET', '/api/platform-admin/dunning-notification-events'], ['P-09', 'PlatformAdminQuestionBanksController_banks', 'GET', '/api/platform-admin/question-banks'], ['P-09', 'PlatformAdminQuestionBanksController_grants', 'GET', '/api/platform-admin/question-bank-grants'], ['P-09', 'PlatformAdminQuestionBanksController_upsertGrant', 'PUT', '/api/platform-admin/question-bank-grants'], ['P-09', 'PlatformAdminQuestionBanksController_syncStatus', 'GET', '/api/platform-admin/question-bank-sync-status'], ['P-10', 'PlatformAdminOverviewController_permissions', 'GET', '/api/platform-admin/permissions'], ['P-10', 'PlatformAdminOverviewController_staff', 'GET', '/api/platform-admin/staff'], ['P-10', 'PlatformAdminOverviewController_upsertStaff', 'PUT', '/api/platform-admin/staff'], ['P-10', 'PlatformAdminOverviewController_updateStaffStatus', 'PATCH', '/api/platform-admin/staff/status'], ['P-11', 'PlatformAdminAuditController_logs', 'GET', '/api/platform-admin/audit-logs'], ['P-11', 'PlatformAdminAuditController_exportLogs', 'GET', '/api/platform-admin/audit-logs/export'], ['P-12', 'PlatformAdminAuditController_rules', 'GET', '/api/platform-admin/audit-alert-rules'], ['P-12', 'PlatformAdminAuditController_alerts', 'GET', '/api/platform-admin/audit-alerts'], ['P-12', 'PlatformAdminAuditController_updateAlert', 'POST', '/api/platform-admin/audit-alerts/status'], ['P-12', 'PlatformAdminAuditController_channels', 'GET', '/api/platform-admin/audit-notification-channels'], ['P-12', 'PlatformAdminAuditController_upsertChannel', 'PUT', '/api/platform-admin/audit-notification-channels'], ['P-12', 'PlatformAdminAuditController_events', 'GET', '/api/platform-admin/audit-notification-events'], ]; const operations = operationRows.map(([pageId, operationId, method, path]) => ({ pageId, operationId, method, path })); const operationById = Object.fromEntries(operations.map(operation => [operation.operationId, operation])); const navEdges = [ ['nav.p-01.p-02', 'P-01', 'P-02', '[data-nav="tenants"]'], ['nav.p-01.p-06', 'P-01', 'P-06', '[data-nav="billing"]'], ['nav.p-01.p-12', 'P-01', 'P-12', '[data-nav="alerts"],[data-alert-detail]'], ['nav.p-02.p-03', 'P-02', 'P-03', '[data-tenant-detail]'], ['nav.p-03.p-04', 'P-03', 'P-04', '[data-action="edit-billing-profile"]'], ['nav.p-03.p-05', 'P-03', 'P-05', '[data-action="create-subscription-for-tenant"]'], ['nav.p-03.p-06', 'P-03', 'P-06', '[data-action="tenant-to-billing"]'], ['nav.p-05.p-06', 'P-05', 'P-06', '[data-action="subscription-to-billing"]'], ['nav.p-05.p-07', 'P-05', 'P-07', '[data-action="subscriptions-to-usage"]'], ['nav.p-06.p-08', 'P-06', 'P-08', '[data-nav="dunning"]'], ['nav.p-11.p-12', 'P-11', 'P-12', '[data-action="jump-related-alert"]'], ].map(([id, fromPageId, toPageId, selector]) => ({ id, fromPageId, toPageId, selector, implemented: true })); const supportingReads = [ { pageId: 'P-09', selector: '[data-action="sync-detail"],[data-action="refresh-bank-sync"]', operationId: 'PlatformAdminQuestionBanksController_syncStatus' }, ]; const trace = []; const decoratedActionIds = new Set(); const selectorCollisions = new Set(); const explicitResultActionIds = new Set(['act.p-06.01', 'act.p-06.04', 'act.p-09.01', 'act.p-09.05']); function pushTrace(entry) { trace.push({ at: new Date().toISOString(), ...entry }); if (trace.length > 120) trace.splice(0, trace.length - 120); document.documentElement.dataset.platformContractEvents = String(trace.length); } function decorate(root = document, pageId = '') { const shell = root.querySelector?.('.page-shell'); if (shell && pageId) { const pageOperations = operations.filter(operation => operation.pageId === pageId); shell.dataset.specPageId = pageId; shell.dataset.operationIds = pageOperations.map(operation => operation.operationId).join(' '); shell.dataset.operationContracts = pageOperations.map(operation => `${operation.method} ${operation.path}`).join(' | '); } actions.filter(action => action.pageId === pageId).forEach(action => { root.querySelectorAll?.(action.selector).forEach(element => { const existingActionId = element.dataset.specActionId; if (existingActionId && existingActionId !== action.id) selectorCollisions.add(`${existingActionId} -> ${action.id}`); element.dataset.specActionId = action.id; element.dataset.specActionMode = action.mode; element.dataset.specEffect = action.effect; element.dataset.mobileBoundary = action.mobile; const operation = operationById[action.operationIds[0]]; if (operation) { element.dataset.operationId = operation.operationId; element.dataset.operationMethod = operation.method; element.dataset.operationPath = operation.path; } decoratedActionIds.add(action.id); }); }); supportingReads.filter(read => read.pageId === pageId).forEach(read => { const operation = operationById[read.operationId]; root.querySelectorAll?.(read.selector).forEach(element => { element.dataset.specSupportingRead = 'true'; element.dataset.specEffect = 'read'; if (operation) { element.dataset.operationId = operation.operationId; element.dataset.operationMethod = operation.method; element.dataset.operationPath = operation.path; } }); }); navEdges.filter(edge => edge.fromPageId === pageId).forEach(edge => { root.querySelectorAll?.(edge.selector).forEach(element => { element.dataset.navEdgeId = edge.id; element.dataset.navTargetPage = edge.toPageId; }); }); window.__PLATFORM_SPEC_COVERAGE__ = coverage(); } function eventContract(target) { const element = target?.closest?.('[data-spec-action-id]'); if (!element) return null; return { element, actionId: element.dataset.specActionId, operationId: element.dataset.operationId || '', requestId: `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}` }; } document.addEventListener('click', event => { const contract = eventContract(event.target); if (!contract) return; contract.element.dataset.contractRequestId = contract.requestId; pushTrace({ phase: 'before', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId }); setTimeout(() => pushTrace({ phase: 'after', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId, result: 'handled', pageId: document.querySelector('.page-shell')?.dataset.specPageId || '' }), 0); }, true); document.addEventListener('change', event => { const contract = eventContract(event.target); if (!contract) return; pushTrace({ phase: 'after', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId, result: 'changed' }); }, true); const coverage = () => ({ expected: 59, total: actions.length, unique: new Set(actions.map(action => action.id)).size, catalogued: actions.filter(action => action.label && action.kind).length, selectorDeclared: actions.filter(action => action.selector).length, nativeMetadata: actions.filter(action => action.mode === 'native').length, contractMetadata: actions.filter(action => action.mode === 'contract').length, nativeMapped: actions.filter(action => action.mode === 'native' && decoratedActionIds.has(action.id)).length, dedicatedExecutor: explicitResultActionIds.size, dedicatedExecutorDefinition: 'actions with explicit success/failure result recording', reachable: actions.filter(action => action.implemented && action.selector).length, mountedThisSession: decoratedActionIds.size, decoratedInSession: decoratedActionIds.size, notYetDecorated: actions.filter(action => !decoratedActionIds.has(action.id)).map(action => action.id), implemented: actions.filter(action => action.implemented && action.selector).length, unimplemented: actions.filter(action => !action.implemented || !action.selector).map(action => action.id), selectorCollisions: Array.from(selectorCollisions), apiExact: operations.filter(operation => operation.operationId && operation.method && operation.path).length, uiOnlyExplained: actions.filter(action => action.operationIds.length === 0).length, effectDeclared: actions.filter(action => action.effect).length, mobileDeclared: actions.filter(action => action.mobile).length, actuallyExecuted: new Set(trace.filter(entry => entry.phase === 'result' && entry.result === 'success').map(entry => entry.actionId)).size, executionNote: 'catalogue and selector metadata are not counted as successful business execution', navigation: { expected: 11, total: navEdges.length, unique: new Set(navEdges.map(edge => edge.id)).size }, pageBindings: { expected: 43, total: operations.length, unique: new Set(operations.map(operation => `${operation.pageId}:${operation.operationId}`)).size }, }); const assertions = { pages: new Set(actions.map(action => action.pageId)).size === 12, actionIds: actions.every(action => action.id.startsWith(`act.${action.pageId.toLowerCase()}.`)), duplicateActions: new Set(actions.map(action => action.id)).size === actions.length, operationContracts: operations.every(operation => /^(GET|POST|PUT|PATCH|DELETE)$/.test(operation.method) && operation.path.startsWith('/api/')), navTargets: navEdges.every(edge => actions.some(action => action.pageId === edge.fromPageId) && actions.some(action => action.pageId === edge.toPageId)), }; window.GONGXUE_PLATFORM_SPEC = { actions, operations, navEdges, supportingReads }; window.__GONGXUE_ACTION_CONTRACT__ = { coverage, assertions, trace }; window.decoratePlatformSpec = decorate; window.recordPlatformSpecResult = (actionId, result = {}) => pushTrace({ phase: 'result', actionId, ...result }); window.__PLATFORM_CONTRACT_EVENTS__ = trace; window.__PLATFORM_SPEC_COVERAGE__ = coverage(); })();