fix(web): stop presenting an unscored case as a failed analysis, and four smaller things

From clicking through the redesigned UI:

- scoring a case without a model registry painted a red failure across a case that had in
  fact analysed fine. It is now a quiet note saying the model term contributes 0, because
  scoring is an optional fourth of the rank, not the analysis.
- the MLflow default moves to port 5001. On macOS, AirPlay Receiver owns 5000, which is why
  the registry answered "403" rather than refusing the connection; docker-compose publishes
  5001 to match.
- a funnel step that kept nothing drew a visible bar. Zero now draws zero.
- "1 candidates".
- the funnel's fixed grid columns forced a horizontal scrollbar on the report.

The report also lists the top undecided candidates now: the first thing anyone opens has no
decisions in it, and "Shortlisted (0)" alone said nothing about what the tool found.

Tests: api 77, web 32; ruff, mypy, svelte-check clean.
This commit is contained in:
Kemal Yaylali
2026-09-12 08:49:00 +01:00
parent 07a01715fd
commit 3ab404ebe5
12 changed files with 100 additions and 9 deletions
+8
View File
@@ -36,6 +36,8 @@ from app.services.scoring import score_job
logger = logging.getLogger(__name__)
router = APIRouter()
REPORT_TOP = 5
async def _case_or_404(session: SessionDep, case_id: uuid.UUID) -> Case:
case = await case_view.get_case(session, case_id)
@@ -208,6 +210,11 @@ async def report(case_id: uuid.UUID, session: SessionDep) -> ReportOut:
]
shortlisted, dismissed = decided(DecisionState.shortlisted), decided(DecisionState.dismissed)
top = [
CandidateOut.from_candidate(c, labels)
for c in view.candidates
if c.variant.decision is None
][:REPORT_TOP]
prediction = next((c.variant.prediction for c in view.candidates if c.variant.prediction), None)
return ReportOut(
case=_as_case_out(case, view.job, len(shortlisted)),
@@ -222,4 +229,5 @@ async def report(case_id: uuid.UUID, session: SessionDep) -> ReportOut:
),
shortlisted=shortlisted,
dismissed=dismissed,
top=top,
)