feat: 增加仅检查 MCP 工具并完善已提交 Alpha 指标展示
Deploy production / deploy (push) Successful in 57s

This commit is contained in:
yuxuanhui
2026-09-11 13:14:27 +08:00
parent f25161d624
commit 7e990b9a69
12 changed files with 311 additions and 63 deletions
+31 -1
View File
@@ -22,6 +22,8 @@ from ..models import Account, Alpha, BacktestItem, Job, JobItem, ResearchRequest
from ..research.serialization import encode_snapshot
from ..research.workspace_contracts import FieldAvailabilityInput
from ..schemas import JobInput
from ..submission import CheckInput, correlation_allows_check, create_check_job, local_alpha, source
from ..submission import fingerprint as submission_fingerprint
from .contracts import DirectCandidate, History
from .queries import EvidenceQueries, page
@@ -51,6 +53,11 @@ class ResearchAccess:
"confirmation": "调用者须已获本批执行授权;直接提交后返回稳定运行 ID",
"duplicate_policies": ["reject", "rerun"], "permissions": sorted(self.principal.scopes),
"metadata_only": True, "actual_platform_allowance": None,
"submission_check": {
"check_with": "check_submission", "read_with": "get_submission_check",
"job_with": "get_refresh_job", "max_targets": 1,
"description_writeback": True, "production_submission": False,
},
"self_correlation": {
"check_with": "check_self_correlation", "read_with": "get_self_correlation",
"job_with": "get_refresh_job", "max_targets": 100, "source": "local",
@@ -156,7 +163,7 @@ class ResearchAccess:
async def refresh_job(self, args):
job = await self.db.get(Job, args.job_id)
if not job or job.kind not in {"catalog_sync", "field_sync", "pnl_refresh", "self_correlation"}:
if not job or job.kind not in {"catalog_sync", "field_sync", "pnl_refresh", "self_correlation", "submission_check"}:
raise ResearchError("NOT_FOUND", "研究刷新任务不存在")
result = await self.business.get_job_status(args.job_id)
query = select(JobItem).where(JobItem.job_id == job.id, JobItem.error.is_not(None))
@@ -187,6 +194,29 @@ class ResearchAccess:
status = "not_cached" if not data["cached"] else "stale" if data["result"]["stale"] else "available"
return {"alpha_id": args.alpha_id, "source": "local", "status": status, **data}
async def submission_check_context(self, args):
"""Read cached review context and check evidence without upstream requests."""
alpha = await local_alpha(self.db, args.alpha_id)
context = source(alpha.raw)
job = await self.db.scalar(select(Job).where(
Job.kind == "submission_check", Job.payload["alpha_ids"][0].as_string() == args.alpha_id
).order_by(Job.created_at.desc()).limit(1))
return {"alpha_id": args.alpha_id, "snapshot": submission_fingerprint(context),
**context, "descriptions": {key: item["description"] for key, item in context["sections"].items()},
"can_check": alpha.status == "UNSUBMITTED" and await correlation_allows_check(self.db, args.alpha_id),
"checks": alpha.checks, "source": "local_cache", "production_submission": False,
"job_id": job.id if job else None, "job_status": job.status if job else None,
"checked_at": job.checkpoint.get("checked_at") if job else None}
async def check_submission(self, args):
"""Queue the shared reviewed-description/check flow; never submit an Alpha."""
job = await create_check_job(self.db, args.alpha_id, CheckInput(
snapshot=args.snapshot, descriptions=args.descriptions))
self.wake = "jobs"
return {"job_id": job.id, "status": job.status, "alpha_id": args.alpha_id,
"production_submission": False, "job_with": "get_refresh_job",
"read_with": "get_submission_check"}
async def history(self, args):
return await self.evidence.history(args)