From cab4cea50237e3053a39741f81dabc153062c3e4 Mon Sep 17 00:00:00 2001 From: Protocol Zero <257158451+Protocol-zero-0@users.noreply.github.com> Date: Sat, 6 Jun 2026 17:17:26 +0000 Subject: [PATCH 1/3] Refresh dashboard phase one --- tests/test_web_app.py | 136 ++++++++++++++ web/app.py | 33 ---- web/static/css/style.css | 104 ++++++++++- web/static/js/app.js | 370 ++++++++++++++++++++++----------------- web/static/js/i18n.js | 251 ++++++++++++++++++++++++++ web/templates/index.html | 257 ++++++++++++--------------- 6 files changed, 809 insertions(+), 342 deletions(-) create mode 100644 web/static/js/i18n.js diff --git a/tests/test_web_app.py b/tests/test_web_app.py index b8c28f0..93f7a00 100644 --- a/tests/test_web_app.py +++ b/tests/test_web_app.py @@ -1,4 +1,5 @@ import json +import re import tempfile import unittest from datetime import datetime @@ -10,6 +11,13 @@ from web import app as web_app +REPO_ROOT = Path(__file__).resolve().parents[1] + + +def _read(path: str) -> str: + return (REPO_ROOT / path).read_text(encoding="utf-8") + + class WebAppTests(unittest.TestCase): def setUp(self): self.client = web_app.app.test_client() @@ -47,6 +55,134 @@ def test_manual_post_api_returns_gone_in_fixed_flow_mode(self): self.assertIn("removed", payload["error"].lower()) +class DashboardRefreshTests(unittest.TestCase): + def setUp(self): + self.client = web_app.app.test_client() + + def test_dashboard_and_stats_routes_return_200(self): + with tempfile.TemporaryDirectory() as tmpdir: + old_db_path = database.DB_PATH + old_database_url = database.DATABASE_URL + for attr in ("pg_conn", "sqlite_conn", "conn"): + if hasattr(database._local, attr): + try: + getattr(database._local, attr).close() + except Exception: + pass + setattr(database._local, attr, None) + try: + database.DATABASE_URL = "" + database.DB_PATH = Path(tmpdir) / "stats.db" + database.init_db() + + self.assertEqual(self.client.get("/").status_code, 200) + self.assertEqual(self.client.get("/api/stats").status_code, 200) + finally: + for attr in ("pg_conn", "sqlite_conn", "conn"): + if hasattr(database._local, attr): + try: + getattr(database._local, attr).close() + except Exception: + pass + setattr(database._local, attr, None) + database.DATABASE_URL = old_database_url + database.DB_PATH = old_db_path + + def test_dashboard_main_tabs_are_phase1_six_with_advanced_collapsed(self): + html = _read("web/templates/index.html") + main_tabs = re.findall(r'

${esc(tr('experiments.discoveryProgress'))}

-

Auto Research: ${esc(auto.status || 'not_started')} ${auto.stage ? `/ ${esc(auto.stage)}` : ''}

-

Submission: ${esc(insight.submission_status || 'not_started')} | Run count: ${runs.length}

-

Workspace: ${esc(data.workspace_root || '-')}

+

${esc(tr('label.autoResearch', { status: `${auto.status || 'not_started'}${auto.stage ? ` / ${auto.stage}` : ''}` }))}

+

${esc(tr('label.submissionRunCount', { status: insight.submission_status || 'not_started', count: runs.length }))}

+

${esc(tr('label.workspace', { path: data.workspace_root || '-' }))}

${renderTrackChips(data.planned_tracks)}
${renderManuscriptBlockers(plan.manuscript_blockers || {}, 8)} - ${auto.last_note ? `

Latest: ${esc(auto.last_note)}

` : ''} - ${auto.last_error ? `

Error: ${esc(auto.last_error)}

` : ''} + ${auto.last_note ? `

${esc(tr('common.latest'))} ${esc(auto.last_note)}

` : ''} + ${auto.last_error ? `

${esc(tr('common.error'))} ${esc(auto.last_error)}

` : ''}
-

Experiment Area

-

Experiment path: ${esc(data.experiment_root || '-')}

-

Canonical Run: ${esc(data.canonical_run_id || canonical?.id || '-')}

+

${esc(tr('label.experimentArea'))}

+

${esc(tr('label.experimentPath', { path: '' }))} ${esc(data.experiment_root || '-')}

+

${esc(tr('label.canonicalRun', { run: '' }))} ${esc(data.canonical_run_id || canonical?.id || '-')}

-

Experiment Plan Area

-

Plan path: ${esc(data.plan_root || '-')}

- ${jsonPreview(plan.latest_status, 'No latest_status.json')} +

${esc(tr('label.experimentPlanArea'))}

+

${esc(tr('label.planPath', { path: '' }))} ${esc(data.plan_root || '-')}

+ ${jsonPreview(plan.latest_status, tr('common.noLatestStatus'))}
-

Generated Manuscript Area

-

Generated manuscript path: ${esc(data.paper_root || '-')}

+

${esc(tr('label.generatedManuscriptArea'))}

+

${esc(tr('label.generatedManuscriptPath', { path: '' }))} ${esc(data.paper_root || '-')}

- ${paperUrls.index ? `` : ''} - ${paperUrls.pdf ? `` : ''} - ${paperUrls.tex ? `` : ''} + ${paperUrls.index ? `` : ''} + ${paperUrls.pdf ? `` : ''} + ${paperUrls.tex ? `` : ''}
${renderPaperAssetLinks(insight.id, paperAssets)}
`; - html += `

Plan Snapshot

- ${jsonPreview(plan.experiment_spec, 'No experiment_spec.json')} - ${jsonPreview(plan.manuscript_blockers, 'No manuscript blockers')} - ${jsonPreview(plan.manuscript_input_state, 'No manuscript_input_state.json')}`; + html += `

${esc(tr('label.planSnapshot'))}

+ ${jsonPreview(plan.experiment_spec, tr('common.noExperimentSpec'))} + ${jsonPreview(plan.manuscript_blockers, tr('common.noManuscriptBlockers'))} + ${jsonPreview(plan.manuscript_input_state, tr('common.noManuscriptInputState'))}`; if (runs.length) { - html += '

Experiment History

'; + html += `

${esc(tr('label.experimentHistory'))}

`; for (const run of runs) { const color = experimentStatusColor(run.status); const artifactSummary = Object.entries(run.artifact_counts || {}) @@ -2406,25 +2406,25 @@ window._dg = { ? `${esc(run.hypothesis_verdict.toUpperCase())}` : ''; const badges = []; - if (canonical && canonical.id === run.id) badges.push('canonical'); - if (run.has_plot_artifacts) badges.push('plot'); - if (run.has_bundle) badges.push('submission bundle'); + if (canonical && canonical.id === run.id) badges.push(tr('label.canonical')); + if (run.has_plot_artifacts) badges.push(tr('label.plot')); + if (run.has_bundle) badges.push(tr('label.submissionBundleBadge')); html += `
- Experiment Run ${run.id} + ${esc(tr('label.experimentRun', { id: run.id }))} ${esc(run.status || 'unknown')} ${verdict} ${badges.map(label => `${esc(label)}`).join('')}
- Iterations: ${run.iterations_total || 0} (${run.iterations_kept || 0} kept) - Claims: ${run.claim_count || 0} - ${run.effect_pct != null ? `Effect: ${run.effect_pct.toFixed(2)}%` : ''} - ${artifactSummary ? `Artifacts: ${esc(artifactSummary)}` : ''} + ${esc(tr('label.iterations', { total: run.iterations_total || 0, kept: run.iterations_kept || 0 }))} + ${esc(tr('common.claimsCount', { count: run.claim_count || 0 }))} + ${run.effect_pct != null ? `${esc(tr('label.effect', { effect: run.effect_pct.toFixed(2) + '%' }))}` : ''} + ${artifactSummary ? `${esc(tr('label.artifacts', { artifacts: artifactSummary }))}` : ''}
${run.error_message ? `
${esc(trunc(run.error_message, 220))}
` : ''}
- +
`; } @@ -2439,7 +2439,7 @@ window._dg = { modal.innerHTML = `
${html}`; document.body.appendChild(modal); } catch (e) { - alert('Failed to load idea history: ' + e.message); + alert(tr('common.failedToLoadIdeaHistory', { message: e.message })); } }, @@ -2452,19 +2452,19 @@ window._dg = { let html = `
-

Experiment #${run.id}: ${esc(run.insight_title || '')}

- Status: ${esc(run.status)} | Verdict: ${esc(run.hypothesis_verdict || 'pending')} +

${esc(tr('label.experimentRun', { id: `#${run.id}` }))}: ${esc(run.insight_title || '')}

+ ${esc(tr('label.statusVerdict', { status: run.status, verdict: run.hypothesis_verdict || 'pending' }))}
-

Metrics

-

Baseline: ${run.baseline_metric_value || '?'} | Best: ${run.best_metric_value || '?'} | Effect: ${run.effect_pct != null ? run.effect_pct.toFixed(2) + '%' : '?'}

-

Iterations: ${run.iterations_total || 0} total, ${run.iterations_kept || 0} kept

- ${run.codebase_url ? `

Codebase: ${esc(run.codebase_url)}

` : ''} - ${run.error_message ? `

Error: ${esc(run.error_message)}

` : ''}`; +

${esc(tr('label.metrics'))}

+

${esc(tr('label.baseline', { value: run.baseline_metric_value || '?' }))} | ${esc(tr('label.best', { value: run.best_metric_value || '?' }))} | ${esc(tr('label.effect', { effect: run.effect_pct != null ? run.effect_pct.toFixed(2) + '%' : '?' }))}

+

${esc(tr('label.iterations', { total: run.iterations_total || 0, kept: run.iterations_kept || 0 }))}

+ ${run.codebase_url ? `

${esc(tr('label.codebase'))} ${esc(run.codebase_url)}

` : ''} + ${run.error_message ? `

${esc(tr('common.error'))} ${esc(run.error_message)}

` : ''}`; if (iters.length) { - html += '

Iteration History

'; + html += `

${esc(tr('label.iterationHistory'))}

#PhaseMetricStatusDescription
`; for (const it of iters.slice(-30)) { const sColor = it.status === 'keep' ? '#3d8b5e' : it.status === 'crash' ? '#c4453a' : '#9a9088'; html += ``; @@ -2473,7 +2473,7 @@ window._dg = { } if (claims.length) { - html += '

Experimental Claims

'; + html += `

${esc(tr('label.experimentalClaims'))}

`; for (const cl of claims) { const vColor = cl.verdict === 'confirmed' ? '#3d8b5e' : cl.verdict === 'refuted' ? '#c4453a' : '#a8842a'; html += `
@@ -2490,7 +2490,7 @@ window._dg = { modal.innerHTML = `
${html}`; document.body.appendChild(modal); } catch (e) { - alert('Failed to load: ' + e.message); + alert(tr('common.failedToLoad', { message: e.message })); } }, @@ -2523,14 +2523,14 @@ window._dg = {

${esc(res.title)}

- ${res.paper_count} papers · ${res.claim_count} claims · ${res.contradiction_count} contradictions + ${esc(tr('common.papersCount', { count: res.paper_count }))} · ${esc(tr('common.claimsCount', { count: res.claim_count }))} · ${esc(tr('common.contradictionsCount', { count: res.contradiction_count }))}
${bodyHtml}
`; document.body.appendChild(modal); } catch (e) { - alert('Failed to load proposal: ' + e.message); + alert(tr('common.failedToLoadProposal', { message: e.message })); } }, }; diff --git a/web/static/js/i18n.js b/web/static/js/i18n.js index 6625e85..8f86ebe 100644 --- a/web/static/js/i18n.js +++ b/web/static/js/i18n.js @@ -96,6 +96,204 @@ "empty.manuscriptAssets": "No generated manuscript assets.", "empty.experimentRuns": "No experiment runs yet for this discovery.", "empty.experimentRunCreated": "No experiment run created yet", + "common.secondsAgo": "{count}s ago", + "common.minutesAgo": "{count}m ago", + "common.hoursAgo": "{count}h ago", + "common.daysAgo": "{count}d ago", + "common.eventsCount": "{count} events", + "common.papersCount": "{count} papers", + "common.papersUnit": "papers", + "common.methodsCount": "{count} methods", + "common.methodsUnit": "methods", + "common.datasetsCount": "{count} datasets", + "common.gapsCount": "{count} gaps", + "common.gapsUnit": "gaps", + "common.mentionsCount": "{count} mentions", + "common.resultsCount": "{count} results", + "common.claimsCount": "{count} claims", + "common.contradictionsCount": "{count} contradictions", + "common.paperShort": "{count}p", + "common.loading": "Loading...", + "common.loadingDetails": "Loading details...", + "common.failedToLoad": "Failed to load: {message}", + "common.failedToLoadDetails": "Failed to load details.", + "common.failedToLoadProposal": "Failed to load proposal: {message}", + "common.failedToLoadIdeaHistory": "Failed to load idea history: {message}", + "common.errorLoadingData": "Error loading data.", + "common.metric": "Metric:", + "common.noData": "No data", + "common.noneOption": "(none)", + "common.methodDataset": "Method / Dataset", + "common.clickToExplore": "Click to explore", + "common.emptyGraphNode": "empty", + "common.untitled": "Untitled", + "common.untitledPaper": "Untitled paper", + "common.unknown": "Unknown", + "common.scoreValue": "score {score}/5", + "common.valueScore": "value {score}/5", + "common.onDataset": "{method} on {dataset}", + "common.latest": "Latest:", + "common.error": "Error:", + "common.viewDetails": "View Details", + "common.viewRunDetails": "View Run Details", + "common.openPdf": "Open PDF", + "common.openTex": "Open TeX", + "common.generated": "Generated: {time}", + "common.updated": "Updated: {time}", + "common.noLatestStatus": "No latest_status.json", + "common.noExperimentSpec": "No experiment_spec.json", + "common.noManuscriptBlockers": "No manuscript blockers", + "common.noManuscriptInputState": "No manuscript_input_state.json", + "common.openArxiv": "Open on arXiv", + "explore.workstream": "Workstream", + "explore.openGap": "Open gap", + "explore.whyNow": "Why now: {text}", + "explore.whatPeopleWorking": "What People Are Working On", + "explore.whereGapsAre": "Where The Gaps Are", + "explore.recurringThemes": "Recurring Themes", + "explore.methodsDatasets": "Methods & Datasets", + "explore.noneYet": "None yet", + "explore.paperCluster": "Paper Cluster", + "explore.paperClusters": "Paper Clusters", + "explore.sharedEntities": "shared entities: {entities}", + "explore.clusterWeakSignals": "This node has {count} papers, but the current graph signals were not strong enough to form stable clusters yet.", + "explore.coreEntities": "Core Entities", + "explore.keyLinks": "Key Links", + "explore.researchInsights": "Research Insights ({count})", + "explore.universal": "Universal", + "explore.crossDomain": "Cross-domain", + "explore.alsoAppliesTo": "Also applies to:", + "explore.universalPatterns": "Universal Patterns ({count})", + "explore.leafDomain": "Leaf domain — see the detailed analysis below", + "label.discovery": "Discovery", + "label.researchInsight": "Research Insight", + "label.opportunity": "Opportunity", + "label.claim": "Claim", + "label.results": "Results", + "label.evidence": "Evidence:", + "label.hypothesis": "Hypothesis:", + "label.experiment": "Experiment:", + "label.impact": "Impact:", + "label.proposedExperiment": "Proposed Experiment", + "label.potentialImpact": "Potential Impact", + "label.previewProposal": "Preview Proposal", + "label.formalStructure": "Formal Structure:", + "label.transformation": "Transformation:", + "label.fields": "Fields:", + "label.predictions": "Predictions:", + "label.strongestChallenge": "Strongest Challenge:", + "label.problem": "Problem:", + "label.weakness": "Weakness:", + "label.method": "Method:", + "label.baselines": "Baselines:", + "label.datasets": "Datasets:", + "label.compute": "Compute:", + "label.mode": "Mode:", + "label.fixedAutomaticPipeline": "Fixed automatic pipeline", + "label.adversarial": "Adversarial: {score}/10", + "label.experimentStatus": "Experiment: {status}", + "label.verdict": "Verdict: {verdict}", + "label.internalStage": "Internal stage:", + "label.novelty": "Novelty:", + "label.cpuCheck": "CPU Check:", + "label.effect": "Effect: {effect}", + "label.tier": "Tier {tier}", + "label.baseline": "Baseline: {value}", + "label.best": "Best: {value}", + "label.iterations": "Iterations: {total} ({kept} kept)", + "label.repo": "Repo: {repo}", + "label.discoveryId": "Discovery {id}", + "label.experimentRun": "Experiment Run {id}", + "label.experimentRunStatus": "Experiment Run {id} [{status}]", + "label.manuscriptId": "Manuscript #{id}", + "label.submissionBundle": "Submission Bundle: {status}", + "label.latestFileStatus": "Latest file status:", + "label.latestError": "Latest error:", + "label.experimentRuns": "Experiment runs: {count}", + "label.latestExperimentRun": "Latest experiment run: {status}", + "label.experimentPath": "Experiment path: {path}", + "label.planPath": "Plan path: {path}", + "label.generatedManuscriptPath": "Generated manuscript path: {path}", + "label.canonicalRun": "Canonical Run: {run}", + "label.autoResearch": "Auto Research: {status}", + "label.submissionRunCount": "Submission: {status} | Run count: {count}", + "label.workspace": "Workspace: {path}", + "label.statusVerdict": "Status: {status} | Verdict: {verdict}", + "label.metrics": "Metrics", + "label.codebase": "Codebase:", + "label.phase": "Phase", + "label.metric": "Metric", + "label.status": "Status", + "label.description": "Description", + "label.experimentalClaims": "Experimental Claims", + "label.artifacts": "Artifacts: {artifacts}", + "label.iterationHistory": "Iteration History", + "label.experimentHistory": "Experiment History", + "label.planSnapshot": "Plan Snapshot", + "label.experimentArea": "Experiment Area", + "label.experimentPlanArea": "Experiment Plan Area", + "label.generatedManuscriptArea": "Generated Manuscript Area", + "label.openManuscriptPage": "Open manuscript page", + "label.openPaperPreview": "Open paper preview", + "label.openPaperPage": "Open paper page", + "label.usePaperPage": "Use the paper page to open only the assets that actually exist for this manuscript.", + "label.planFilesReady": "experiment spec, evidence plan, manuscript state, manuscript blockers", + "label.waitingPlanFiles": "waiting for plan files", + "label.planFile.experimentSpec": "experiment spec", + "label.planFile.evidencePlan": "evidence plan", + "label.planFile.manuscriptState": "manuscript state", + "label.planFile.manuscriptBlockers": "manuscript blockers", + "label.paperBlocked": "Paper blocked:", + "label.moreBlockers": "{count} more blocker(s)", + "label.canonical": "canonical", + "label.plot": "plot", + "label.submissionBundleBadge": "submission bundle", + "meta.confirmed": "Confirmed", + "meta.refuted": "Refuted", + "meta.hitRate": "Hit Rate", + "meta.signalTypePerformance": "Signal Type Performance", + "meta.signal": "Signal", + "meta.total": "Total", + "meta.learnedSignalWeights": "Learned Signal Weights", + "status.novelty.novel": "NOVEL", + "status.novelty.partial": "PARTIAL", + "status.novelty.exists": "EXISTS", + "status.novelty.unchecked": "UNCHECKED", + "service.state.missing": "missing", + "service.state.active": "active", + "service.state.ready": "ready", + "service.detail.paper": "Batch {batch}, {status}", + "service.detail.auto": "{jobs} jobs, {experiments} experiments, {blocked} blocked", + "service.detail.evo": "{count} active sessions", + "service.detail.paperOrchestra": "{bundles} bundles, {drafting} drafting", + "service.detail.gpu": "{running} running, {queued} queued, {workers} workers", + "status.auto.unavailable": "Auto Research status unavailable.", + "status.auto.running": "RUNNING", + "status.auto.stopped": "STOPPED", + "status.auto.interval": "Interval: {seconds}s", + "status.auto.jobs": "Jobs: {count}", + "status.auto.completed": "Completed: {count}", + "status.auto.blocked": "Blocked: {count}", + "providers.failed": "Failed to load provider data.", + "providers.unknown": "Unknown", + "search.failed": "Search failed.", + "agenda.dispatch.auto": "auto", + "agenda.dispatch.link": "link existing", + "agenda.dispatch.enqueue": "enqueue fresh", + "agenda.dispatch.none": "no dispatch", + "agenda.yamlPlaceholder": "version: v1\nname: ...", + "agenda.active": "active · #{id} {name}", + "agenda.focus": "focus", + "agenda.preferKeywords": "prefer.keywords", + "agenda.preferTiers": "prefer.tiers", + "agenda.reject": "reject", + "agenda.selection": "selection #{id}", + "agenda.status": "status", + "agenda.candidatesJson": "candidates_json", + "agenda.pasteYamlFirst": "Paste YAML first.", + "manuscript.venueCount": "{count} venues", + "manuscript.templatePlaceholder": "template_id (e.g. iclr2026)", + "manuscript.pageCountPlaceholder": "page_count (optional)", "experiments.services": "Automation Services", "experiments.readOnly": "Read-only automatic mode", "experiments.autoResearch": "Auto Research", @@ -157,6 +355,7 @@ "status.evo.ready": "EvoScientist ready", "status.evo.missing": "EvoScientist missing", "feed.title": "Pipeline Event Feed", + "feed.initialCount": "0 events", "providers.title": "LLM Providers", "providers.refresh": "Auto-refresh 10s", "providers.calls": "Calls", @@ -199,6 +398,7 @@ "manuscript.stateJson": "State JSON (for route preview)", "manuscript.lintPayload": "Lint payload (template_id + source)", "manuscript.noResult": "No result yet.", + "manuscript.venueCountInitial": "— venues", "manuscript.errorVenues": "ERROR (venues)", "manuscript.venues": "VENUES", "manuscript.stateParseError": "State JSON parse error: {message}", @@ -300,6 +500,204 @@ "empty.manuscriptAssets": "暂无生成稿件资产。", "empty.experimentRuns": "该深度发现暂无实验运行。", "empty.experimentRunCreated": "尚未创建实验运行", + "common.secondsAgo": "{count} 秒前", + "common.minutesAgo": "{count} 分钟前", + "common.hoursAgo": "{count} 小时前", + "common.daysAgo": "{count} 天前", + "common.eventsCount": "{count} 个事件", + "common.papersCount": "{count} 篇文献", + "common.papersUnit": "篇文献", + "common.methodsCount": "{count} 个方法", + "common.methodsUnit": "个方法", + "common.datasetsCount": "{count} 个数据集", + "common.gapsCount": "{count} 个空白", + "common.gapsUnit": "个空白", + "common.mentionsCount": "{count} 次提及", + "common.resultsCount": "{count} 条结果", + "common.claimsCount": "{count} 条论断", + "common.contradictionsCount": "{count} 个矛盾", + "common.paperShort": "{count} 篇", + "common.loading": "加载中...", + "common.loadingDetails": "正在加载详情...", + "common.failedToLoad": "加载失败:{message}", + "common.failedToLoadDetails": "详情加载失败。", + "common.failedToLoadProposal": "研究提案加载失败:{message}", + "common.failedToLoadIdeaHistory": "深度发现历史加载失败:{message}", + "common.errorLoadingData": "数据加载出错。", + "common.metric": "指标:", + "common.noData": "无数据", + "common.noneOption": "(无)", + "common.methodDataset": "方法 / 数据集", + "common.clickToExplore": "点击探索", + "common.emptyGraphNode": "空", + "common.untitled": "未命名", + "common.untitledPaper": "未命名文献", + "common.unknown": "未知", + "common.scoreValue": "分数 {score}/5", + "common.valueScore": "价值 {score}/5", + "common.onDataset": "{method} 在 {dataset}", + "common.latest": "最新:", + "common.error": "错误:", + "common.viewDetails": "查看详情", + "common.viewRunDetails": "查看运行详情", + "common.openPdf": "打开 PDF", + "common.openTex": "打开 TeX", + "common.generated": "生成时间:{time}", + "common.updated": "更新时间:{time}", + "common.noLatestStatus": "无 latest_status.json", + "common.noExperimentSpec": "无 experiment_spec.json", + "common.noManuscriptBlockers": "无稿件阻塞项", + "common.noManuscriptInputState": "无 manuscript_input_state.json", + "common.openArxiv": "在 arXiv 打开", + "explore.workstream": "工作流", + "explore.openGap": "开放空白", + "explore.whyNow": "为何现在:{text}", + "explore.whatPeopleWorking": "大家正在做什么", + "explore.whereGapsAre": "空白在哪里", + "explore.recurringThemes": "反复出现的主题", + "explore.methodsDatasets": "方法与数据集", + "explore.noneYet": "暂无", + "explore.paperCluster": "文献簇", + "explore.paperClusters": "文献簇", + "explore.sharedEntities": "共享实体:{entities}", + "explore.clusterWeakSignals": "该节点有 {count} 篇文献,但当前图谱信号还不足以形成稳定文献簇。", + "explore.coreEntities": "核心实体", + "explore.keyLinks": "关键关系", + "explore.researchInsights": "研究洞见({count})", + "explore.universal": "通用", + "explore.crossDomain": "跨领域", + "explore.alsoAppliesTo": "同样适用于:", + "explore.universalPatterns": "通用模式({count})", + "explore.leafDomain": "叶子领域 — 详见下方分析", + "label.discovery": "深度发现", + "label.researchInsight": "研究洞见", + "label.opportunity": "机会点", + "label.claim": "论断", + "label.results": "结果", + "label.evidence": "证据:", + "label.hypothesis": "假设:", + "label.experiment": "实验:", + "label.impact": "影响:", + "label.proposedExperiment": "拟议实验", + "label.potentialImpact": "潜在影响", + "label.previewProposal": "预览提案", + "label.formalStructure": "形式结构:", + "label.transformation": "转换:", + "label.fields": "领域:", + "label.predictions": "预测:", + "label.strongestChallenge": "最强挑战:", + "label.problem": "问题:", + "label.weakness": "弱点:", + "label.method": "方法:", + "label.baselines": "基线:", + "label.datasets": "数据集:", + "label.compute": "算力:", + "label.mode": "模式:", + "label.fixedAutomaticPipeline": "固定自动流水线", + "label.adversarial": "对抗评分:{score}/10", + "label.experimentStatus": "实验:{status}", + "label.verdict": "结论:{verdict}", + "label.internalStage": "内部阶段:", + "label.novelty": "新颖性:", + "label.cpuCheck": "CPU 检查:", + "label.effect": "效果:{effect}", + "label.tier": "层级 {tier}", + "label.baseline": "基线:{value}", + "label.best": "最佳:{value}", + "label.iterations": "迭代:{total}(保留 {kept})", + "label.repo": "仓库:{repo}", + "label.discoveryId": "深度发现 {id}", + "label.experimentRun": "实验运行 {id}", + "label.experimentRunStatus": "实验运行 {id} [{status}]", + "label.manuscriptId": "稿件 #{id}", + "label.submissionBundle": "投稿包:{status}", + "label.latestFileStatus": "最新文件状态:", + "label.latestError": "最新错误:", + "label.experimentRuns": "实验运行:{count}", + "label.latestExperimentRun": "最新实验运行:{status}", + "label.experimentPath": "实验路径:{path}", + "label.planPath": "计划路径:{path}", + "label.generatedManuscriptPath": "生成稿件路径:{path}", + "label.canonicalRun": "标准运行:{run}", + "label.autoResearch": "自动研究:{status}", + "label.submissionRunCount": "投稿:{status} | 运行数:{count}", + "label.workspace": "工作区:{path}", + "label.statusVerdict": "状态:{status} | 结论:{verdict}", + "label.metrics": "指标", + "label.codebase": "代码库:", + "label.phase": "阶段", + "label.metric": "指标", + "label.status": "状态", + "label.description": "描述", + "label.experimentalClaims": "实验论断", + "label.artifacts": "产物:{artifacts}", + "label.iterationHistory": "迭代历史", + "label.experimentHistory": "实验历史", + "label.planSnapshot": "计划快照", + "label.experimentArea": "实验区域", + "label.experimentPlanArea": "实验计划区域", + "label.generatedManuscriptArea": "生成稿件区域", + "label.openManuscriptPage": "打开稿件页面", + "label.openPaperPreview": "打开稿件预览", + "label.openPaperPage": "打开稿件页面", + "label.usePaperPage": "使用稿件页面只打开该稿件实际存在的资产。", + "label.planFilesReady": "实验规格、证据计划、稿件状态、稿件阻塞项", + "label.waitingPlanFiles": "等待计划文件", + "label.planFile.experimentSpec": "实验规格", + "label.planFile.evidencePlan": "证据计划", + "label.planFile.manuscriptState": "稿件状态", + "label.planFile.manuscriptBlockers": "稿件阻塞项", + "label.paperBlocked": "稿件阻塞:", + "label.moreBlockers": "还有 {count} 个阻塞项", + "label.canonical": "标准", + "label.plot": "图表", + "label.submissionBundleBadge": "投稿包", + "meta.confirmed": "已确认", + "meta.refuted": "已否定", + "meta.hitRate": "命中率", + "meta.signalTypePerformance": "信号类型表现", + "meta.signal": "信号", + "meta.total": "总数", + "meta.learnedSignalWeights": "学习到的信号权重", + "status.novelty.novel": "新颖", + "status.novelty.partial": "部分存在", + "status.novelty.exists": "已存在", + "status.novelty.unchecked": "未检查", + "service.state.missing": "缺失", + "service.state.active": "活跃", + "service.state.ready": "就绪", + "service.detail.paper": "批大小 {batch},{status}", + "service.detail.auto": "{jobs} 个任务,{experiments} 个实验,{blocked} 个阻塞", + "service.detail.evo": "{count} 个活跃会话", + "service.detail.paperOrchestra": "{bundles} 个投稿包,{drafting} 个草稿", + "service.detail.gpu": "{running} 个运行中,{queued} 个排队,{workers} 个工作器", + "status.auto.unavailable": "自动研究状态不可用。", + "status.auto.running": "运行中", + "status.auto.stopped": "已停止", + "status.auto.interval": "间隔:{seconds} 秒", + "status.auto.jobs": "任务:{count}", + "status.auto.completed": "完成:{count}", + "status.auto.blocked": "阻塞:{count}", + "providers.failed": "模型服务数据加载失败。", + "providers.unknown": "未知", + "search.failed": "搜索失败。", + "agenda.dispatch.auto": "自动", + "agenda.dispatch.link": "关联现有", + "agenda.dispatch.enqueue": "新建入队", + "agenda.dispatch.none": "不分发", + "agenda.yamlPlaceholder": "version: v1\nname: ...", + "agenda.active": "活跃 · #{id} {name}", + "agenda.focus": "重点", + "agenda.preferKeywords": "偏好关键词", + "agenda.preferTiers": "偏好层级", + "agenda.reject": "拒绝条件", + "agenda.selection": "选择 #{id}", + "agenda.status": "状态", + "agenda.candidatesJson": "候选 JSON", + "agenda.pasteYamlFirst": "请先粘贴 YAML。", + "manuscript.venueCount": "{count} 个会议模板", + "manuscript.templatePlaceholder": "template_id(例如 iclr2026)", + "manuscript.pageCountPlaceholder": "页数(可选)", "experiments.services": "自动化服务", "experiments.readOnly": "只读自动模式", "experiments.autoResearch": "自动研究", @@ -361,6 +759,7 @@ "status.evo.ready": "EvoScientist 就绪", "status.evo.missing": "EvoScientist 缺失", "feed.title": "流水线事件流", + "feed.initialCount": "0 个事件", "providers.title": "模型服务商", "providers.refresh": "10 秒自动刷新", "providers.calls": "调用", @@ -403,6 +802,7 @@ "manuscript.stateJson": "状态 JSON(用于路由预览)", "manuscript.lintPayload": "格式检查载荷(template_id + source)", "manuscript.noResult": "暂无结果。", + "manuscript.venueCountInitial": "— 个会议模板", "manuscript.errorVenues": "错误(会议模板)", "manuscript.venues": "会议模板", "manuscript.stateParseError": "状态 JSON 解析错误:{message}", diff --git a/web/static/js/manuscript_routing.js b/web/static/js/manuscript_routing.js index cf2120b..80310d8 100644 --- a/web/static/js/manuscript_routing.js +++ b/web/static/js/manuscript_routing.js @@ -36,7 +36,7 @@ if (status >= 300) { setResult(tr("manuscript.errorVenues"), body); return; } const venues = (body && body.venues) || []; const badge = $("venueCountBadge"); - if (badge) badge.textContent = `${venues.length} venues`; + if (badge) badge.textContent = tr("manuscript.venueCount", { count: venues.length }); setResult(tr("manuscript.venues"), venues); } diff --git a/web/templates/index.html b/web/templates/index.html index 774a7fd..d2d7f9d 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -185,7 +185,7 @@

Current Processing

0
-

Idle

+

@@ -300,13 +300,13 @@

Generated Manuscript

0
-

No generated manuscript runs are ready yet.

+

- +
@@ -314,14 +314,14 @@

Generated Manuscript

Discovery

-

No ready discoveries yet. Automatic discovery is still filtering candidates.

+

@@ -345,11 +345,10 @@

Auto Research

Fixed automatic mode -
- Auto Research status unavailable. +
-

No auto research jobs yet.

+

@@ -368,7 +367,7 @@

Discovery Experiment Runs

-

No discoveries are active yet. The automatic queue will start them when ready.

+

Upload agenda (YAML) - +
@@ -483,7 +482,7 @@

Research Agenda

Manuscript Routing & Format Lint

- — venues + — venues
@@ -507,15 +506,15 @@

Manuscript Routing & Format Lint

Lint payload (template_id + source) - - + +
-
No result yet.
+

                         
#${esc(tr('label.phase'))}${esc(tr('label.metric'))}${esc(tr('label.status'))}${esc(tr('label.description'))}
${it.iteration_number}${esc(it.phase)}${it.metric_value != null ? it.metric_value.toFixed(6) : '-'}${esc(it.status)}${esc(trunc(it.description || '', 60))}