|
| 1 | +# Guided Triage — Root-Cause Finding in LOGAN |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Give a user who is *not* a log expert a fast path from **symptom** to **root cause**. |
| 6 | +Instead of staring at a raw file, they answer a few templated questions and LOGAN runs |
| 7 | +a *recipe* — a fixed combination of the primitives it already has (search, filter, |
| 8 | +highlight, time-gaps, trends, baseline, pin-as-finding) — and pins clickable findings. |
| 9 | + |
| 10 | +## Design principle: symptom-first, domain second |
| 11 | + |
| 12 | +Users reliably know the **symptom** ("it crashed", "it's slow"). They do *not* always |
| 13 | +know the **domain** (Android vs. embedded vs. backend). So: |
| 14 | + |
| 15 | +- **Symptom is the front door** — a small menu of universal failure modes. |
| 16 | +- **Domain is a *pack*** that sits underneath and only swaps the keyword/field |
| 17 | + dictionaries each recipe uses (e.g. what "crash" looks like in logcat vs. serial). |
| 18 | +- Domain is **auto-detected** from log content, with a manual override. |
| 19 | + |
| 20 | +``` |
| 21 | +User → [Symptom menu] → recipe runs → findings pinned → [drill-down: 3 next moves] |
| 22 | + ↑ |
| 23 | + [Domain pack] supplies the keywords/fields the recipe searches for |
| 24 | +``` |
| 25 | + |
| 26 | +This beats a pure domain menu because symptoms generalize and domains don't, and it |
| 27 | +beats a flat search box because the user doesn't have to know *what* to search for. |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## The symptom menu (8 recipes) |
| 32 | + |
| 33 | +Each recipe is a one-tap action. "Primitives" lists the existing LOGAN/MCP tools it |
| 34 | +chains. Every recipe ends by pinning results via `logan_report_finding` so they are |
| 35 | +clickable in the viewer. |
| 36 | + |
| 37 | +| # | Symptom (button) | What the recipe does | Primitives used | |
| 38 | +|---|-------------------------|--------------------------------------------------------------------------------------|-----------------| |
| 39 | +| 1 | **It crashed / died** | Find fatal/exception/stack-trace markers; jump to the **last line before death**; pin the 50 lines before it as context. | `logan_investigate_crashes`, `logan_search`, `logan_get_lines`, `logan_report_finding` | |
| 40 | +| 2 | **It froze / hung** | Rank **time gaps**; surface the last log line before the silence; flag stuck/repeating loops. | `logan_time_gaps`, `logan_get_lines`, `logan_search` | |
| 41 | +| 3 | **It's slow** | Trend duration/latency fields over time; list slowest operations; flag timeout/GC spikes. | `logan_trend_fields`, `logan_trend_series`, `logan_search` | |
| 42 | +| 4 | **Error storm** | Plot error-rate over time and find the **spike**; show the **first occurrence** of each unique error; group by component. | `logan_analyze`, `logan_trend_series`, `logan_search` | |
| 43 | +| 5 | **Won't start** | Walk the startup sequence; surface config / port-bind / permission / missing-dependency errors. | `logan_search`, `logan_get_lines`, `logan_analyze` | |
| 44 | +| 6 | **Connection drops** | Find disconnect/reconnect/retry/timeout events; correlate by endpoint/peer. | `logan_search`, `logan_trend_correlate`, `logan_trend_transitions` | |
| 45 | +| 7 | **Intermittent / flaky**| Detect what **flipped** (`transitions`); correlate event-presence vs. a state field. | `logan_trend_transitions`, `logan_trend_correlate` | |
| 46 | +| 8 | **Wrong / odd value** | Trend the suspect field; find **where it changed**; correlate with surrounding events. | `logan_trend_series`, `logan_trend_transitions`, `logan_trend_correlate` | |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +## Templated guiding questions (narrowing) |
| 51 | + |
| 52 | +After a symptom is picked, LOGAN asks at most 2–3 of these to narrow the recipe. |
| 53 | +All are optional — an unanswered question falls back to an auto-detect default. |
| 54 | + |
| 55 | +| Question | Options / input | Effect on the recipe | |
| 56 | +|-----------------------------------|---------------------------------------|--------------------------------------------------------------| |
| 57 | +| **When did you first notice it?** | timestamp · "around line N" · *don't know* | Sets the focus window. *Don't know* → auto-jump to first error. | |
| 58 | +| **Which component / module?** | dropdown auto-filled from discovered components | Filters every search to that component. | |
| 59 | +| **Got a known-good run?** | pick a saved baseline · no | Switches the recipe to a **baseline compare** (diff vs. good). | |
| 60 | +| **One-off or repeating?** | once · keeps happening | Repeating → prefer `transitions`/`correlate` over single-hit search. | |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +## The drill-down (5-Whys) |
| 65 | + |
| 66 | +After the first finding, *always* offer the same three next moves. This is what turns a |
| 67 | +single hit into a root cause: |
| 68 | + |
| 69 | +1. **What happened right BEFORE this?** → pin the preceding N lines / last state change. |
| 70 | +2. **What else fired at the SAME time?** → correlate events in the same time bucket. |
| 71 | +3. **Has this happened before in the file?** → all earlier occurrences + first one. |
| 72 | + |
| 73 | +Each move re-pins findings and pushes a breadcrumb so the user can step back. |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## Domain packs |
| 78 | + |
| 79 | +A pack is just a dictionary swapped in behind the recipes — same recipes, different |
| 80 | +vocabulary. Detected from log content; user-overridable. |
| 81 | + |
| 82 | +| Pack | "Crash" markers (ex.) | Latency field (ex.) | Notes | |
| 83 | +|-----------------|----------------------------------------|---------------------|-------| |
| 84 | +| **Generic** | `FATAL`, `exception`, `panic`, `core dumped`, stack frames | `duration`, `elapsed`, `ms` | default fallback | |
| 85 | +| **Android/logcat** | `FATAL EXCEPTION`, `ANR`, `signal 11`, `tombstone` | `Displayed`, `Choreographer` skipped frames | level column, tags | |
| 86 | +| **Embedded/serial** | `HardFault`, `assert`, `watchdog`, `reset` | tick counters | no timestamps common → use line order | |
| 87 | +| **Web/backend** | `5xx`, `traceback`, `OOMKilled`, `segfault` | `latency_ms`, `rt`, `took` | request-id correlation | |
| 88 | +| **Automotive/MF4** | signal threshold breaches | numeric signal channels | routes through the Trends/signal engine | |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +## UX surface |
| 93 | + |
| 94 | +- **Entry point:** an "Investigate / Guide me" panel in the activity bar (or extend the |
| 95 | + existing `logan_triage` flow). |
| 96 | +- **Breadcrumb:** the investigation path with a **Back** button. |
| 97 | +- **Findings:** every recipe step pins a clickable annotation (existing finding system). |
| 98 | +- **Free-text box:** a plain-English question that the AI agent maps onto a recipe — the |
| 99 | + escape hatch for anything the 8 buttons don't cover. |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +## Build order (recommended) |
| 104 | + |
| 105 | +1. **This spec** — symptom → recipe table (done). |
| 106 | +2. Recipe engine: a small map of `symptom → ordered list of primitive calls`, reusing |
| 107 | + the existing MCP tools; output always pinned as findings. |
| 108 | +3. The panel UI (symptom buttons + guiding questions + breadcrumb). |
| 109 | +4. Domain-pack dictionaries + auto-detection. |
| 110 | +5. NL→recipe box on top of the agent. |
| 111 | + |
| 112 | +Recipes are pure composition of primitives that already exist, so step 2 needs no new |
| 113 | +analysis engine — only wiring + a keyword/field dictionary per pack. |
0 commit comments