@switch (activePanel()) { @case ('scorecard') { @if (scorecardRows().length > 0) { @for (card of scorecardRows(); track card.flowId) { {{ flowName(card.flowId) }} {{ card.starts.toLocaleString() }} {{ completionRate(card) }}% {{ card.medianDuration }} {{ card.handovers.toLocaleString() }} } } @else { No flow matches “{{ query() }}”. } } @case ('drop-off') { Node-by-node traffic for the published graph. The band on the left is the share of people who reached a node and never left it — the darker the band, the more conversations end there. @if (traffic().length > 0) {
    @for (node of traffic(); track node.nodeId) {
  1. }
} @else { No node matches “{{ query() }}”. } } @case ('intents') { Where each intent’s conversations actually ended. Recognition is not the measure here — an intent can be understood every time and still hand every conversation to a person. @if (intentRows().length > 0) {
    @for (row of intentRows(); track row.intent) {
  • }
} @else { No intent matches “{{ query() }}”. } } @case ('breakpoints') { @if (breakpointRows().length > 0) { @for (breakpoint of breakpointRows(); track breakpoint.id) { {{ breakpoint.nodeLabel }} {{ flowName(breakpoint.flowId) }} {{ breakpoint.failure }} {{ breakpoint.occurrences.toLocaleString() }} } } @else { No breakpoint matches “{{ query() }}”. } } } @switch (activePanel()) { @case ('scorecard') { @if (selectedScorecard(); as card) {

{{ flowName(card.flowId) }}

{{ selectedFlow()?.language }} · {{ selectedFlow()?.status }}

Funnel, last 30 days
Open breakpoints @if (scorecardBreakpoints().length > 0) { @for (breakpoint of scorecardBreakpoints(); track breakpoint.id) { } } @else {

No diagnosed breakpoint on this flow.

}
} @else { Select a flow to see its funnel. } } @case ('drop-off') { @if (selectedNode(); as node) {

{{ node.label }}

{{ node.type }}

Traffic
Where to look first @if (worstNode(); as worst) { } @if (slowestNode(); as slowest) { }

A node people sit on for a long time before leaving is usually a wording problem, not a routing one.

} @else { Select a node to see its traffic. } } @case ('intents') { @if (selectedIntent(); as row) {

{{ row.intent }}

{{ flowName(row.flowId) }}

Outcomes @for (outcome of outcomes; track outcome) { }
Volume

“No matching path” is the honest failure here: the intent arrived and the flow had nowhere to send it.

} @else { Select an intent to see where it ends up. } } @case ('breakpoints') { @if (selectedBreakpoint(); as breakpoint) {

{{ breakpoint.nodeLabel }}

{{ flowName(breakpoint.flowId) }}

Failure

{{ breakpoint.diagnosis }}

Mitigation {{ breakpoint.mitigation }}
@if (selectedFix(); as fix) {
The simulator can apply

{{ fix.title }}

    @for (add of fix.adds; track add) {
  • {{ add }}
  • }
} @else {

No automatic repair for this one — the mitigation is an authoring change, not a graph edit.

} } @else { Select a breakpoint to see the diagnosis. } } }