Normalize sibling scores to 100%, improve justification prompt, add AI availability indicator

Addresses three UX/semantic gaps: scores within a sibling group weren't constrained to sum to 100%, the leaf justification prompt asked the LLM to justify a selection rather than explain a score, and there was no persistent visual indicator of AI availability.

Score normalization

LlmService.normalizeToHundred() applies the largest-remainder method so any batch of sibling scores sums to exactly 100. Applied after all LLM response parsing and in the LOCAL_ONNX embedding path. All-zero batches (no match) are left unchanged.

// Before: {BP.001: 70, BP.002: 30, BP.003: 50} → sum = 150
// After:  {BP.001: 47, BP.002: 20, BP.003: 33} → sum = 100

Justification prompt (prompts/justify-leaf.txt)

Rewritten to ask the LLM to explain why the percentage at each node turned out as it did (aspects of the requirement that matched/didn't match), rather than justifying why a particular leaf was "chosen". Keeps the root→leaf path with scores as context.

AI availability indicator

Added a persistent Bootstrap badge in the navbar (#aiStatusBadge) that shows 🟢/🔴/⚠️ status on page load and re-polls /api/ai-status every 30 seconds.

Original prompt

Können wir die Prozentzahlen so bilden, dass die Summe aller Prozentzahlen auf den Blättern stets 100% ergeben muss? Können wir die request Justifikation so erstellen lassen, dass klar erkennbar ist, wie die entscheidung an jedem knoten von der wurzel zum Blatt gefällt worden ist? Die ki muss auch nicht eine Entscheidung für ein bestimmtes Blatt rechtfertigen sondern sollte nur begründen warum die Prozentzahl so ausgefallen ist. Kann man sichtbar machen ob die ki gerade anfragen entgegen nehmen kann?


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Merge request reports

Loading