Skip to content

Commit 02ed907

Browse files
JihaoXinclaude
andcommitted
Add phase status display to web portal (research/dev/review badges)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ce19b79 commit 02ed907

File tree

2 files changed

+111
-4
lines changed

2 files changed

+111
-4
lines changed

ark/webapp/routes.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,59 @@ def _read_current_iteration(project_dir: Path) -> int:
495495
return 0
496496

497497

498+
def _read_phase_status(project_dir: Path, project) -> dict:
499+
"""Read current phase, dev iteration, and review iteration status.
500+
501+
Returns a dict with: phase, dev_iter, max_dev_iter, review_iter, max_review_iter
502+
"""
503+
state_dir = project_dir / "auto_research" / "state"
504+
result = {
505+
"phase": "",
506+
"dev_iter": 0,
507+
"max_dev_iter": project.max_dev_iterations,
508+
"review_iter": 0,
509+
"max_review_iter": project.max_iterations,
510+
}
511+
512+
# Read dev phase state
513+
dev_state_file = state_dir / "dev_phase_state.yaml"
514+
if dev_state_file.exists():
515+
try:
516+
ds = yaml.safe_load(dev_state_file.read_text()) or {}
517+
result["dev_iter"] = int(ds.get("iteration", 0))
518+
dev_status = ds.get("status", "pending")
519+
if dev_status == "complete":
520+
result["phase"] = "review"
521+
elif dev_status == "in_progress":
522+
result["phase"] = "dev"
523+
except Exception:
524+
pass
525+
526+
# Read paper (review) state
527+
paper_state_file = state_dir / "paper_state.yaml"
528+
if paper_state_file.exists():
529+
try:
530+
ps = yaml.safe_load(paper_state_file.read_text()) or {}
531+
reviews = ps.get("reviews") or []
532+
if reviews:
533+
result["review_iter"] = int(reviews[-1].get("iteration", len(reviews)))
534+
result["phase"] = "review"
535+
paper_status = ps.get("status", "")
536+
if paper_status in ("accepted", "accepted_pending_cleanup"):
537+
result["phase"] = "accepted"
538+
except Exception:
539+
pass
540+
541+
# Check for research phase
542+
deep_research_file = state_dir / "deep_research.md"
543+
if deep_research_file.exists() and not result["phase"]:
544+
result["phase"] = "research"
545+
elif not result["phase"] and project.status == "running":
546+
result["phase"] = "initializing"
547+
548+
return result
549+
550+
498551
def _read_cost_report(project_dir: Path) -> dict:
499552
"""Read cost_report.yaml and return a slim summary suitable for the UI.
500553
@@ -1260,6 +1313,7 @@ async def api_get_project(project_id: str, request: Request):
12601313
"score_history": _read_score_history(pdir),
12611314
"current_iteration": _read_current_iteration(pdir),
12621315
"max_iterations": project.max_iterations,
1316+
"phase_status": _read_phase_status(pdir, project),
12631317
"has_pdf": pdf is not None,
12641318
"has_pdf_upload": bool(project.has_pdf_upload),
12651319
"slurm_job_id": project.slurm_job_id,

ark/webapp/static/app.html

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ <h3>User Settings & API Keys</h3>
13221322
// detail info
13231323
info_venue: 'Venue', info_user: 'User', info_model: 'Model',
13241324
info_environment: 'Environment', info_created: 'Created', info_updated: 'Updated',
1325-
info_status: 'Status',
1325+
info_status: 'Status', info_phase: 'Phase',
13261326
completed_iter: 'Completed (%d iterations)',
13271327
running_iter: 'Running (%d / %d iterations)',
13281328
running_plain: 'Running',
@@ -1434,7 +1434,7 @@ <h3>User Settings & API Keys</h3>
14341434
status_waiting_template: '⏳ في انتظار القالب', status_pending: '⏳ في قائمة الانتظار',
14351435
info_venue: 'المؤتمر', info_user: 'المستخدم', info_model: 'النموذج',
14361436
info_environment: 'البيئة', info_created: 'تاريخ الإنشاء', info_updated: 'آخر تحديث',
1437-
info_status: 'الحالة',
1437+
info_status: 'الحالة', info_phase: 'المرحلة',
14381438
completed_iter: 'مكتمل (%d تكرارات)',
14391439
running_iter: 'قيد التشغيل (%d / %d تكرارات)',
14401440
running_plain: 'قيد التشغيل',
@@ -1537,7 +1537,7 @@ <h3>User Settings & API Keys</h3>
15371537
status_waiting_template: '⏳ 等待模板', status_pending: '⏳ 排队中',
15381538
info_venue: '会议', info_user: '用户', info_model: '模型',
15391539
info_environment: '环境', info_created: '创建时间', info_updated: '更新时间',
1540-
info_status: '状态',
1540+
info_status: '状态', info_phase: '阶段',
15411541
completed_iter: '已完成(%d 次迭代)',
15421542
running_iter: '运行中(%d / %d 次迭代)',
15431543
running_plain: '运行中',
@@ -1966,6 +1966,59 @@ <h3>User Settings & API Keys</h3>
19661966
</div>`;
19671967
}
19681968

1969+
// ══════════════════════════════════════════════════════
1970+
// Phase status helper
1971+
// ══════════════════════════════════════════════════════
1972+
function _renderPhaseStatus(p) {
1973+
const ps = p.phase_status;
1974+
if (!ps || !ps.phase) {
1975+
// Fallback for older backends
1976+
return `<div><b>Iteration:</b> ${p.current_iteration || 0} / ${p.max_iterations}</div>`;
1977+
}
1978+
1979+
const phaseLabels = {
1980+
research: t('phase_research') || 'Research',
1981+
dev: t('phase_dev') || 'Dev',
1982+
review: t('phase_review') || 'Review',
1983+
accepted: '✓ Accepted',
1984+
initializing: 'Initializing',
1985+
};
1986+
const phaseColors = {
1987+
research: '#8b5cf6',
1988+
dev: '#f59e0b',
1989+
review: '#3b82f6',
1990+
accepted: '#10b981',
1991+
initializing: 'var(--text-muted)',
1992+
};
1993+
1994+
const phaseName = phaseLabels[ps.phase] || ps.phase;
1995+
const phaseColor = phaseColors[ps.phase] || 'var(--text)';
1996+
1997+
// Build iteration detail string
1998+
let iterDetail = '';
1999+
if (ps.phase === 'dev') {
2000+
iterDetail = ` (${ps.dev_iter}/${ps.max_dev_iter})`;
2001+
} else if (ps.phase === 'review') {
2002+
iterDetail = ` (${ps.review_iter}/${ps.max_review_iter})`;
2003+
}
2004+
2005+
const badge = `<span style="display:inline-block;padding:1px 8px;border-radius:10px;font-size:.82em;font-weight:600;color:#fff;background:${phaseColor}">${esc(phaseName)}${iterDetail}</span>`;
2006+
2007+
// Build dev + review iteration summary line
2008+
const parts = [];
2009+
if (ps.max_dev_iter > 0) {
2010+
parts.push(`Dev ${ps.dev_iter}/${ps.max_dev_iter}`);
2011+
}
2012+
if (ps.max_review_iter > 0) {
2013+
parts.push(`Review ${ps.review_iter}/${ps.max_review_iter}`);
2014+
}
2015+
const iterLine = parts.length
2016+
? `<div style="color:var(--text-muted);font-size:.88em;margin-top:2px">${parts.join(' · ')}</div>`
2017+
: '';
2018+
2019+
return `<div><b>${t('info_phase') || 'Phase'}:</b> ${badge}${iterLine}</div>`;
2020+
}
2021+
19692022
// ══════════════════════════════════════════════════════
19702023
// Project Detail
19712024
// ══════════════════════════════════════════════════════
@@ -2024,7 +2077,7 @@ <h3>User Settings & API Keys</h3>
20242077
<div><b>Project ID:</b> <code style="font-size:.85em;background:var(--bg-hover);padding:1px 5px;border-radius:4px">${esc(p.id)}</code></div>
20252078
<div><b>${t('info_venue')}:</b> ${esc(p.venue)}</div>
20262079
<div><b>${t('info_model')}:</b> ${esc(p.model || 'claude-sonnet-4-6')}</div>
2027-
<div><b>Iteration:</b> ${p.current_iteration || 0} / ${p.max_iterations}</div>
2080+
${_renderPhaseStatus(p)}
20282081
<div><b>${t('info_environment')}:</b> ${esc(p.environment || 'Local')}</div>
20292082
${condaEnvLine}
20302083
<div><b>${t('info_user')}:</b> ${esc(p.user_email || '')}</div>

0 commit comments

Comments
 (0)