[llvm-branch-commits] [llvm] [llvm-advisor] Add optimization remarks visualization: relational grid, heatmap, Code Explorer and snapshot diff (PR #218692)

Kamini Banait via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 25 07:04:39 PDT 2026


https://github.com/kamini08 created https://github.com/llvm/llvm-project/pull/218692

# Add optimization remarks visualization: relational grid, heatmap, Code Explorer and snapshot diff

This PR is part of my GSoC 2026 project on llvm-advisor. It adds end-to-end support for visualizing and comparing Clang optimization remarks: importing `-fsave-optimization-record` files, analyzing them with new C++ analyzers, and exposing the results through CLI commands and a web UI with a heatmap, Code Explorer, triage grid, and snapshot diff.

## What this adds

- **Import for `-fsave-optimization-record` YAML files.** `llvm-advisor import foo.opt.yaml` parses a Clang optimization-record file, creates a snapshot and unit, runs the remarks analyzers, and stores the results in the CAS-backed store. The importer also reports clear errors for missing, empty, or malformed YAML, and preserves PGO `Hotness` values when present.

- **Four new C++ analyzers** registered in the capability catalog:
  - `llvm.remarks.summary` - produces overview counts by pass, remark name, and remark type. These numbers back the dashboard cards and the overview page.
  - `llvm.remarks.relational` - builds a columnar table of every remark. Instead of returning a large array of objects, it returns integer-indexed columns plus deduplicated string tables for function, file, pass, and name, which keeps JSON payloads small and makes browser-side filtering fast even for millions of rows.
  - `llvm.remarks.hotspot` - aggregates remarks by function, file, and line, tracking total counts and max hotness. This powers the heatmap and the project stats sidebar.
  - `llvm.remarks.detail` - per-remark detail output used by the detail panel and Code Explorer badges.

- **Heatmap view (`g h`).** A sortable table of hotspots that shows visual hotness bars, status chips (Critical / Moderate / Low), and a project stats sidebar, so you can see at a glance which functions and lines have the most actionable remarks.

- **Code Explorer (`g e`).** Displays source files with remark counts overlaid on each line. It supports `pass` and `function` filters and is linked from the heatmap rows and the triage grid, so you can jump straight from a high-level hotspot to the exact source line that produced it.

- **Snapshot comparison.** The CLI command `llvm-advisor compare --before <snap> --after <snap>` and the Compare UI tab (`g c`) show matched, changed, added, and removed units between two builds, plus an Optimization Impact table that breaks down per-function deltas in missed and passed remarks.

- **HTTP endpoints.** The server exposes REST endpoints for relational remarks, hotspots, per-source-file remarks, and snapshot diffs. The front-end is a single-page app that consumes these endpoints and renders the overview, heatmap, triage grid, Code Explorer, and Compare views.


## Testing

There are 9 lit tests under `llvm/test/tools/llvm-advisor/` covering import, invalid input, relational/hotspot queries, snapshot compare, and the HTTP endpoints.

## Documentation

- **Walkthrough blog post:** [GSoC 2026: llvm-advisor - Optimization Remarks & Visualizations](https://github.com/llvm/llvm-blog-www/pull/93)
- **GSoC 2026 final report:** [final-report-url](https://gist.github.com/kamini08/8ab23822d525856c44ad8315f9f39c01)



>From a0d231eae5338bd347d9b8af3479544285af1acc Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Tue, 26 May 2026 01:56:17 +0530
Subject: [PATCH 01/41] [llvm-advisor] add relational remarks analyzer skeleton

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../config/capabilities/catalog.json          | 33 ++++++++++++++
 .../Analysis/IR/RemarksRelationalAnalyzer.cpp | 43 +++++++++++++++++++
 .../Analysis/IR/RemarksRelationalAnalyzer.h   | 17 ++++++++
 .../src/Capability/CapabilityRegistry.cpp     |  9 ++++
 4 files changed, 102 insertions(+)
 create mode 100644 llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
 create mode 100644 llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.h

diff --git a/llvm/tools/llvm-advisor/config/capabilities/catalog.json b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
index cecae927fd04f..68e919fbd8da9 100644
--- a/llvm/tools/llvm-advisor/config/capabilities/catalog.json
+++ b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
@@ -9,6 +9,39 @@
       "readiness": "L1",
       "dependencies": []
     },
+    {
+      "id": "llvm.remarks.instruction_mix",
+      "name": "Remarks instruction mix",
+      "version": "1",
+      "runner": "builtin.remarks_mix",
+      "summary": "instruction mix requires parsed optimization remarks",
+      "readiness": "L1",
+      "dependencies": [
+        "llvm.remarks.summary"
+      ]
+    },
+    {
+      "id": "llvm.remarks.size_diff",
+      "name": "Remarks size diff",
+      "version": "1",
+      "runner": "builtin.remarks_size_diff",
+      "summary": "size diff requires comparable remarks inputs",
+      "readiness": "L1",
+      "dependencies": [
+        "llvm.remarks.summary"
+      ]
+    },
+    {
+      "id": "llvm.remarks.relational",
+      "name": "Optimization remarks relational view",
+      "version": "1",
+      "runner": "builtin.remarks_relational",
+      "summary": "relational view requires an optimization remarks artifact",
+      "readiness": "L1",
+      "dependencies": [
+        "llvm.remarks.summary"
+      ]
+    },
     {
       "id": "llvm.remarks.detail",
       "name": "Optimization remarks detail",
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
new file mode 100644
index 0000000000000..3b58f82200ad7
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
@@ -0,0 +1,43 @@
+
+#include "Analysis/IR/RemarksRelationalAnalyzer.h"
+#include "Analysis/RemarksAnalysisUtils.h"
+
+using namespace llvm;
+using namespace llvm::advisor;
+
+namespace {
+
+json::Object buildEmptyEnvelope(StringRef RemarksPath) {
+  json::Object Strings{
+      {"pass", json::Array{}},
+      {"name", json::Array{}},
+      {"function", json::Array{}},
+      {"file", json::Array{}},
+  };
+  json::Object Columns{
+      {"pass", json::Array{}},     {"name", json::Array{}},
+      {"type", json::Array{}},     {"function", json::Array{}},
+      {"file", json::Array{}},     {"line", json::Array{}},
+      {"column", json::Array{}},   {"hotness", json::Array{}},
+  };
+  return json::Object{
+      {"schema_version", 1},
+      {"remarks_path", RemarksPath.str()},
+      {"count", static_cast<int64_t>(0)},
+      {"strings", std::move(Strings)},
+      {"columns", std::move(Columns)},
+  };
+}
+
+} // namespace
+
+Expected<std::unique_ptr<CapabilityResult>>
+RemarksRelationalAnalyzer::run(const CapabilityContext &Context) {
+  StringRef CapID = getCapabilityID();
+  StringRef UnitID = Context.Unit.ID;
+  return withRemarksFile(
+      Context, CapID, UnitID,
+      [&](StringRef Path) -> Expected<std::unique_ptr<CapabilityResult>> {
+        return makeJSONResult(CapID, UnitID, buildEmptyEnvelope(Path));
+      });
+}
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.h b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.h
new file mode 100644
index 0000000000000..74aa4ffadb289
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.h
@@ -0,0 +1,17 @@
+
+#pragma once
+
+#include "Analysis/AnalyzerBase.h"
+
+namespace llvm::advisor {
+
+class RemarksRelationalAnalyzer final : public CapabilityRunner {
+public:
+  StringRef getCapabilityID() const override {
+    return "llvm.remarks.relational";
+  }
+  Expected<std::unique_ptr<CapabilityResult>>
+  run(const CapabilityContext &Context) override;
+};
+
+} // namespace llvm::advisor
diff --git a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
index f109ce7abf6cd..78610bb47d1a2 100644
--- a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
+++ b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
@@ -12,6 +12,9 @@
 
 #include "Capability/CapabilityRegistry.h"
 #include "Analysis/IR/RemarksAnalyzer.h"
+#include "Analysis/IR/RemarksMixAnalyzer.h"
+#include "Analysis/IR/RemarksRelationalAnalyzer.h"
+#include "Analysis/IR/RemarksSizeDiffAnalyzer.h"
 #include "Analysis/Inspection/RemarksDetailAnalyzer.h"
 #include "Utils/JSON.h"
 #include "llvm/Support/FileSystem.h"
@@ -219,6 +222,12 @@ CapabilityRegistry::createDeclarativeRunner(const CapabilitySpec &Spec) const {
 void CapabilityRegistry::addBuiltinRunners() {
   consumeError(addRunner("builtin.remarks_summary",
                          std::make_unique<RemarksAnalyzer>()));
+  consumeError(addRunner("builtin.remarks_mix",
+                         std::make_unique<RemarksMixAnalyzer>()));
+  consumeError(addRunner("builtin.remarks_size_diff",
+                         std::make_unique<RemarksSizeDiffAnalyzer>()));
+  consumeError(addRunner("builtin.remarks_relational",
+                         std::make_unique<RemarksRelationalAnalyzer>()));
   consumeError(addRunner("builtin.remarks_detail",
                          std::make_unique<RemarksDetailAnalyzer>()));
 }

>From f8cca187fc6bd6ab91b2ff452058271f2fca4c55 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Tue, 26 May 2026 03:09:47 +0530
Subject: [PATCH 02/41] [llvm-advisor] populate relational remarks columns

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../Analysis/IR/RemarksRelationalAnalyzer.cpp | 117 ++++++++++++++----
 1 file changed, 95 insertions(+), 22 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
index 3b58f82200ad7..db4a8c673a843 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
@@ -1,33 +1,99 @@
 
 #include "Analysis/IR/RemarksRelationalAnalyzer.h"
 #include "Analysis/RemarksAnalysisUtils.h"
+#include "llvm/ADT/StringMap.h"
 
 using namespace llvm;
 using namespace llvm::advisor;
 
 namespace {
 
-json::Object buildEmptyEnvelope(StringRef RemarksPath) {
-  json::Object Strings{
-      {"pass", json::Array{}},
-      {"name", json::Array{}},
-      {"function", json::Array{}},
-      {"file", json::Array{}},
-  };
-  json::Object Columns{
-      {"pass", json::Array{}},     {"name", json::Array{}},
-      {"type", json::Array{}},     {"function", json::Array{}},
-      {"file", json::Array{}},     {"line", json::Array{}},
-      {"column", json::Array{}},   {"hotness", json::Array{}},
-  };
-  return json::Object{
-      {"schema_version", 1},
-      {"remarks_path", RemarksPath.str()},
-      {"count", static_cast<int64_t>(0)},
-      {"strings", std::move(Strings)},
-      {"columns", std::move(Columns)},
-  };
-}
+class StringTable {
+public:
+  unsigned getOrAdd(StringRef S) {
+    auto [It, Inserted] = Index.try_emplace(S, Strings.size());
+    if (Inserted)
+      Strings.emplace_back(S.str());
+    return It->second;
+  }
+
+  json::Array toJSON() const {
+    json::Array Out;
+    Out.reserve(Strings.size());
+    for (const std::string &S : Strings)
+      Out.push_back(S);
+    return Out;
+  }
+
+private:
+  std::vector<std::string> Strings;
+  StringMap<unsigned> Index;
+};
+
+class RelationalBuilder {
+public:
+  void visit(const remarks::Remark &R) {
+    PassCol.push_back(static_cast<int64_t>(Pass.getOrAdd(R.PassName)));
+    NameCol.push_back(static_cast<int64_t>(Name.getOrAdd(R.RemarkName)));
+    TypeCol.push_back(static_cast<int64_t>(R.RemarkType));
+
+    if (R.FunctionName.empty())
+      FunctionCol.push_back(-1);
+    else
+      FunctionCol.push_back(
+          static_cast<int64_t>(Function.getOrAdd(R.FunctionName)));
+
+    if (R.Loc) {
+      FileCol.push_back(
+          static_cast<int64_t>(File.getOrAdd(R.Loc->SourceFilePath)));
+      LineCol.push_back(static_cast<int64_t>(R.Loc->SourceLine));
+      ColumnCol.push_back(static_cast<int64_t>(R.Loc->SourceColumn));
+    } else {
+      FileCol.push_back(-1);
+      LineCol.push_back(-1);
+      ColumnCol.push_back(-1);
+    }
+
+    HotnessCol.push_back(R.Hotness ? static_cast<int64_t>(*R.Hotness) : -1);
+  }
+
+  json::Object render(StringRef RemarksPath) {
+    return json::Object{
+        {"schema_version", 1},
+        {"remarks_path", RemarksPath.str()},
+        {"count", static_cast<int64_t>(PassCol.size())},
+        {"strings", json::Object{
+                        {"pass", Pass.toJSON()},
+                        {"name", Name.toJSON()},
+                        {"function", Function.toJSON()},
+                        {"file", File.toJSON()},
+                    }},
+        {"columns", json::Object{
+                        {"pass", toArray(PassCol)},
+                        {"name", toArray(NameCol)},
+                        {"type", toArray(TypeCol)},
+                        {"function", toArray(FunctionCol)},
+                        {"file", toArray(FileCol)},
+                        {"line", toArray(LineCol)},
+                        {"column", toArray(ColumnCol)},
+                        {"hotness", toArray(HotnessCol)},
+                    }},
+    };
+  }
+
+private:
+  static json::Array toArray(ArrayRef<int64_t> Vs) {
+    json::Array Out;
+    Out.reserve(Vs.size());
+    for (int64_t V : Vs)
+      Out.push_back(V);
+    return Out;
+  }
+
+  StringTable Pass, Name, Function, File;
+  std::vector<int64_t> PassCol, NameCol, TypeCol, FunctionCol, FileCol, LineCol,
+      ColumnCol, HotnessCol;
+};
 
 } // namespace
 
@@ -38,6 +104,13 @@ RemarksRelationalAnalyzer::run(const CapabilityContext &Context) {
   return withRemarksFile(
       Context, CapID, UnitID,
       [&](StringRef Path) -> Expected<std::unique_ptr<CapabilityResult>> {
-        return makeJSONResult(CapID, UnitID, buildEmptyEnvelope(Path));
+        RelationalBuilder Builder;
+        if (Error E = foreachRemark(
+                Path, [&](const remarks::Remark &R) -> Error {
+                  Builder.visit(R);
+                  return Error::success();
+                }))
+          return std::move(E);
+        return makeJSONResult(CapID, UnitID, Builder.render(Path));
       });
 }

>From e949ed18287353c570a41c43a1d9d6f41913eb52 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Tue, 26 May 2026 09:24:58 +0530
Subject: [PATCH 03/41] [llvm-advisor] serve relational remarks at snapshot
 scope

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/HTTPServer.cpp            | 174 ++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 25de405899cc6..b450386bdd2aa 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -493,6 +493,177 @@ static HTTPResult handleGetSummary(CoreClient &Client, StringRef SnapID) {
   return makeJSONSuccess(200, std::move(Summary));
 }
 
+
+namespace {
+
+class StringTable {
+public:
+  unsigned getOrAdd(StringRef S) {
+    auto [It, Inserted] = Index.try_emplace(S, Strings.size());
+    if (Inserted)
+      Strings.emplace_back(S.str());
+    return It->second;
+  }
+
+  json::Array toJSON() const {
+    json::Array Out;
+    Out.reserve(Strings.size());
+    for (const std::string &S : Strings)
+      Out.push_back(S);
+    return Out;
+  }
+
+private:
+  std::vector<std::string> Strings;
+  StringMap<unsigned> Index;
+};
+
+class RelationalMerger {
+public:
+
+  void absorb(const json::Object &Envelope) {
+    if (!Envelope.getBoolean("available").value_or(false))
+      return;
+    const json::Object *Strs = Envelope.getObject("strings");
+    const json::Object *Cols = Envelope.getObject("columns");
+    if (!Strs || !Cols)
+      return;
+
+    int64_t UnitIdx = static_cast<int64_t>(
+        Unit.getOrAdd(Envelope.getString("unit_id").value_or("")));
+
+    std::vector<int64_t> PassRemap = remapStrings(Strs, "pass", Pass);
+    std::vector<int64_t> NameRemap = remapStrings(Strs, "name", Name);
+    std::vector<int64_t> FuncRemap = remapStrings(Strs, "function", Function);
+    std::vector<int64_t> FileRemap = remapStrings(Strs, "file", File);
+
+    const json::Array *PassCol = Cols->getArray("pass");
+    const json::Array *NameCol = Cols->getArray("name");
+    const json::Array *TypeCol = Cols->getArray("type");
+    const json::Array *FuncCol = Cols->getArray("function");
+    const json::Array *FileCol = Cols->getArray("file");
+    const json::Array *LineCol = Cols->getArray("line");
+    const json::Array *ColumnCol = Cols->getArray("column");
+    const json::Array *HotnessCol = Cols->getArray("hotness");
+    if (!PassCol || !NameCol || !TypeCol || !FuncCol || !FileCol || !LineCol ||
+        !ColumnCol || !HotnessCol)
+      return;
+    size_t N = PassCol->size();
+    if (NameCol->size() != N || TypeCol->size() != N ||
+        FuncCol->size() != N || FileCol->size() != N || LineCol->size() != N ||
+        ColumnCol->size() != N || HotnessCol->size() != N)
+      return;
+
+    for (size_t I = 0; I < N; ++I) {
+      UnitColG.push_back(UnitIdx);
+      PassColG.push_back(translate(readInt(*PassCol, I), PassRemap));
+      NameColG.push_back(translate(readInt(*NameCol, I), NameRemap));
+      TypeColG.push_back(readInt(*TypeCol, I));
+      FuncColG.push_back(translate(readInt(*FuncCol, I), FuncRemap));
+      FileColG.push_back(translate(readInt(*FileCol, I), FileRemap));
+      LineColG.push_back(readInt(*LineCol, I));
+      ColumnColG.push_back(readInt(*ColumnCol, I));
+      HotnessColG.push_back(readInt(*HotnessCol, I));
+    }
+  }
+
+  json::Object render(StringRef SnapshotID) {
+    return json::Object{
+        {"snapshot_id", SnapshotID.str()},
+        {"schema_version", 1},
+        {"count", static_cast<int64_t>(UnitColG.size())},
+        {"strings", json::Object{
+                        {"unit", Unit.toJSON()},
+                        {"pass", Pass.toJSON()},
+                        {"name", Name.toJSON()},
+                        {"function", Function.toJSON()},
+                        {"file", File.toJSON()},
+                    }},
+        {"columns", json::Object{
+                        {"unit", toArray(UnitColG)},
+                        {"pass", toArray(PassColG)},
+                        {"name", toArray(NameColG)},
+                        {"type", toArray(TypeColG)},
+                        {"function", toArray(FuncColG)},
+                        {"file", toArray(FileColG)},
+                        {"line", toArray(LineColG)},
+                        {"column", toArray(ColumnColG)},
+                        {"hotness", toArray(HotnessColG)},
+                    }},
+    };
+  }
+
+private:
+
+  static std::vector<int64_t> remapStrings(const json::Object *Strs,
+                                           StringRef Field, StringTable &Dst) {
+    std::vector<int64_t> Map;
+    const json::Array *Arr = Strs->getArray(Field);
+    if (!Arr)
+      return Map;
+    Map.reserve(Arr->size());
+    for (const json::Value &V : *Arr) {
+      std::optional<StringRef> S = V.getAsString();
+      Map.push_back(S ? static_cast<int64_t>(Dst.getOrAdd(*S)) : -1);
+    }
+    return Map;
+  }
+
+  static int64_t readInt(const json::Array &A, size_t I) {
+    return A[I].getAsInteger().value_or(-1);
+  }
+
+
+  static int64_t translate(int64_t Local, ArrayRef<int64_t> Map) {
+    if (Local < 0 || Local >= static_cast<int64_t>(Map.size()))
+      return -1;
+    return Map[Local];
+  }
+
+  static json::Array toArray(ArrayRef<int64_t> Vs) {
+    json::Array Out;
+    Out.reserve(Vs.size());
+    for (int64_t V : Vs)
+      Out.push_back(V);
+    return Out;
+  }
+
+  StringTable Unit, Pass, Name, Function, File;
+  std::vector<int64_t> UnitColG, PassColG, NameColG, TypeColG, FuncColG,
+      FileColG, LineColG, ColumnColG, HotnessColG;
+};
+
+} // namespace
+
+static HTTPResult handleGetRemarksRelational(CoreClient &Client,
+                                             StringRef SnapID) {
+  SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
+  Expected<json::Array> Query = Client.querySnapshot(SnapID, Caps);
+  if (!Query)
+    return makeJSONError(400, Query.takeError());
+
+  RelationalMerger Merger;
+  for (const json::Value &UnitValue : *Query) {
+    const json::Object *UnitObj = UnitValue.getAsObject();
+    const json::Array *Results =
+        UnitObj ? UnitObj->getArray("results") : nullptr;
+    if (!Results)
+      continue;
+    for (const json::Value &ResultValue : *Results) {
+      const json::Object *ResultObj = ResultValue.getAsObject();
+      if (!ResultObj)
+        continue;
+      std::optional<StringRef> Capability = ResultObj->getString("capability");
+      if (!Capability || *Capability != "llvm.remarks.relational")
+        continue;
+      if (const json::Object *ValueObj = ResultObj->getObject("value"))
+        Merger.absorb(*ValueObj);
+    }
+  }
+
+  return makeJSONSuccess(200, Merger.render(SnapID));
+}
+
 static HTTPResult handleGetQueryUnit(CoreClient &Client, StringRef UnitID,
                                      StringRef Capabilities) {
   SmallVector<std::string, 16> Caps = parseCapabilityList(Capabilities);
@@ -742,6 +913,9 @@ Error llvm::advisor::HTTPServer::run() {
                    (Segs[4] == "representations" || Segs[4] == "findings" ||
                     Segs[4] == "mappings" || Segs[4] == "link-units"))
             Res = handleGetEntities(Client, ResolvedSnap, Segs[4]);
+          else if (Segs.size() == 6 && Segs[4] == "remarks" &&
+                   Segs[5] == "relational")
+            Res = handleGetRemarksRelational(Client, ResolvedSnap);
         } else if (Path == "/api/v1/jobs")
           Res = handleGetJobs(Client);
         else if (IsAPI && Segs.size() == 4 && Segs[2] == "jobs")

>From e830887a31802facc102509d9d10cb378d7d67f1 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 27 May 2026 01:04:56 +0530
Subject: [PATCH 04/41] [llvm-advisor] add remarks explorer view and
 compilation_flow insight renderer

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 992 +++++++++++++++++-
 .../src/Client/HTTP/Assets/core.js            |  11 +-
 .../src/Client/HTTP/Assets/index.html         |   3 +
 .../src/Client/HTTP/Assets/index_html.inc     | 992 +++++++++++++++++-
 .../src/Client/HTTP/Assets/shell.js           |   6 +
 .../src/Client/HTTP/Assets/views.js           | 893 ++++++++++++++++
 6 files changed, 2884 insertions(+), 13 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 1cf8ac26eb1a0..1e683cb7259e0 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -689,6 +689,9 @@
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
+  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
+  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
+  remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -788,6 +791,12 @@
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
+  insight: (snapId, name, baseline) => {
+    let url = `/snapshots/${snapId}/insights/${name}`;
+    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
+    return API.get(url);
+  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
@@ -893,7 +902,7 @@
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2015,6 +2024,9 @@
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
+      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
+      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
+      { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2139,6 +2151,9 @@
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
+    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
+    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
+    { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -2258,7 +2273,10 @@
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
+    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
+                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail',
+                      'llvm.debug.summary', 'clang.ast.summary',
+                      'llvm.lto.summary', 'llvm.lto.function_stats'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
@@ -3060,7 +3078,7 @@
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Remarks', 'Artifacts'];
+    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -3121,7 +3139,19 @@
 
     const controls = h('div', { class: 'cap-pills' });
     const body = h('div', { class: 'capability-stack' });
-    const modes = [['remarks', 'Remarks']];
+    const modes = [
+      ['signals', 'Signals'],
+      ['ir', 'IR'],
+      ['cfg', 'CFG'],
+      ['dom', 'Dom'],
+      ['loop', 'Loops'],
+      ['callgraph', 'Call Graph'],
+      ['asm', 'Asm'],
+      ['mca', 'MCA'],
+      ['remarks', 'Remarks'],
+      ['debug', 'Debug'],
+      ['passes', 'Passes'],
+    ];
 
     const loadMode = async (mode, pill) => {
       Array.from(controls.children).forEach(node => node.classList.remove('available'));
@@ -3176,6 +3206,10 @@
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
     // Function list placeholder in sidebar
+    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
+      h('div', { class: 'rail-title' }, 'Functions'),
+      h('div', { class: 'rail-empty' }, 'Loading function list')
+    ));
   },
 
   addSection(parent, title, open, kvPairs) {
@@ -3201,6 +3235,20 @@
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
+    if (tab === 'Diagnostics') {
+      const findings = state.results
+        .filter(r => r.capability.startsWith('clang.diag'))
+        .flatMap(r => r.findings);
+      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
+      const bySev = {};
+      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
+      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
+      return h('div', { class: 'capability-stack' },
+        chartData.length ? UI.barChart(chartData) : null,
+        UI.findingList(findings)
+      );
+    }
+
     if (tab === 'Remarks') {
       const findings = state.results
         .filter(r => r.capability.includes('remarks'))
@@ -3214,6 +3262,13 @@
       );
     }
 
+    if (tab === 'Functions') {
+      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
+      const rows = fnResult?.value?.functions || [];
+      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
+      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
+    }
+
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -3231,6 +3286,9 @@
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
+        this.summaryCard('Functions', metrics.functions, 'neutral'),
+        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
+        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -3254,9 +3312,12 @@
   },
 
   collectOverview(results) {
-    const metrics = { remarks: 0 };
+    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
+      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
+      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
+      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -3266,7 +3327,7 @@
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['llvm.remarks.summary', 'llvm.remarks.detail'];
+      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -3278,6 +3339,30 @@
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
+    // Populate function list in sidebar
+    const fnCard = sidebar.querySelector('#function-list-card');
+    results.forEach(r => {
+      const val = r.value;
+      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
+        if (fnCard) {
+          clearEl(fnCard);
+          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
+          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
+          const list = h('div', { class: 'fn-section' });
+          fns.slice(0, 50).forEach(fn => {
+            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
+              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
+              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
+            ));
+          });
+          if (fns.length > 50) {
+            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
+              `+ ${fns.length - 50} more…`));
+          }
+          fnCard.appendChild(list);
+        }
+      }
+    });
     if (refresh) refresh();
   },
 
@@ -3604,6 +3689,899 @@
 
   </script>
   <script>
+/* ============================================================
+   LLVM Advisor — Timeline View
+   ============================================================ */
+
+const TimelineView = {
+  _metrics: ['unit_count', 'instruction_count', 'health_score'],
+  _colors: {
+    unit_count: '#5B8DB8',
+    instruction_count: '#5DB8A8',
+    health_score: '#6EC9C4',
+    warning_count: '#D4A574',
+    error_count: '#D48B9B',
+  },
+  _snapData: [],
+
+  async render() {
+    const container = h('div', {});
+
+    const chips = h('div', { class: 'metric-chips' });
+    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
+      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
+      const chip = h('div', {
+        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
+        onClick: () => {
+          const idx = this._metrics.indexOf(m);
+          if (idx >= 0) this._metrics.splice(idx, 1);
+          else if (this._metrics.length < 4) this._metrics.push(m);
+          chip.classList.toggle('active');
+          this._drawChart();
+        },
+      },
+        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
+        label
+      );
+      chips.appendChild(chip);
+    });
+    container.appendChild(chips);
+
+    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
+
+    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
+
+    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
+    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
+
+    Shell.renderMain(container);
+    await this._loadData();
+  },
+
+  async _loadData() {
+    const snaps = State.get('snapshots') || [];
+    if (!snaps.length) {
+      this._renderSnapList([]);
+      return;
+    }
+
+    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
+    this._snapData = snaps.map((s, i) => {
+      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
+      return {
+        ...s,
+        unit_count: sum.unit_count ?? s.unit_count ?? 0,
+        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
+        health_score: sum.health_score ?? 0,
+        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
+        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
+        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
+        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
+      };
+    });
+
+    this._renderSnapList(this._snapData);
+    this._renderMetricCards();
+    this._drawChart();
+  },
+
+  _renderMetricCards() {
+    const el = document.getElementById('timeline-metrics');
+    if (!el || !this._snapData.length) return;
+    clearEl(el);
+    const latest = this._snapData[0];
+    const metricDefs = [
+      { key: 'unit_count', label: 'Units' },
+      { key: 'instruction_count', label: 'Instructions' },
+      { key: 'health_score', label: 'Health' },
+      { key: 'remark_count', label: 'Remarks' },
+      { key: 'function_count', label: 'Functions' },
+    ];
+    metricDefs.forEach(m => {
+      const val = latest[m.key] ?? 0;
+      let delta = null, deltaCls = 'neutral';
+      if (this._snapData.length > 1) {
+        const prev = this._snapData[1];
+        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
+        if (d !== 0) {
+          const sign = d > 0 ? '+' : '';
+          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
+          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
+          delta = `${sign}${formatNumber(d)} vs prev`;
+        }
+      }
+      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
+    });
+  },
+
+  _drawChart() {
+    const container = document.getElementById('timeline-chart-container');
+    if (!container) return;
+    clearEl(container);
+    const data = this._snapData;
+    const svgNS = 'http://www.w3.org/2000/svg';
+    const svg = document.createElementNS(svgNS, 'svg');
+    svg.style.width = '100%';
+    svg.style.height = '220px';
+    container.appendChild(svg);
+
+    if (data.length < 2) {
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
+      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
+      svg.appendChild(text);
+      return;
+    }
+
+    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
+    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
+    const chartW = w - padL - padR;
+    const chartH = ht - padT - padB;
+
+    // Horizontal grid lines
+    for (let i = 0; i <= 4; i++) {
+      const y = padT + (chartH * i / 4);
+      const line = document.createElementNS(svgNS, 'line');
+      line.setAttribute('x1', padL); line.setAttribute('y1', y);
+      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
+      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
+      line.setAttribute('stroke-width', '1');
+      svg.appendChild(line);
+    }
+
+    const xStep = chartW / (data.length - 1);
+
+    this._metrics.forEach(m => {
+      const values = data.map(s => Number(s[m]) || 0);
+      const max = Math.max(...values, 1);
+      const min = Math.min(...values, 0);
+      const range = max - min || 1;
+      const color = this._colors[m] || 'var(--accent)';
+
+      const points = data.map((_, i) => {
+        const x = padL + i * xStep;
+        const y = padT + chartH - ((values[i] - min) / range) * chartH;
+        return `${x.toFixed(1)},${y.toFixed(1)}`;
+      });
+
+      // Area fill
+      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
+      const area = document.createElementNS(svgNS, 'polygon');
+      area.setAttribute('points', areaPoints);
+      area.setAttribute('fill', color);
+      area.setAttribute('opacity', '0.08');
+      svg.appendChild(area);
+
+      const poly = document.createElementNS(svgNS, 'polyline');
+      poly.setAttribute('points', points.join(' '));
+      poly.setAttribute('fill', 'none');
+      poly.setAttribute('stroke', color);
+      poly.setAttribute('stroke-width', '2');
+      poly.setAttribute('stroke-linejoin', 'round');
+      svg.appendChild(poly);
+
+      data.forEach((_, i) => {
+        const [x, y] = points[i].split(',');
+        const circle = document.createElementNS(svgNS, 'circle');
+        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
+        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
+        svg.appendChild(circle);
+      });
+
+      // Y-axis labels for first metric only
+      if (m === this._metrics[0]) {
+        for (let i = 0; i <= 4; i++) {
+          const val = min + (range * (4 - i) / 4);
+          const y = padT + (chartH * i / 4);
+          const text = document.createElementNS(svgNS, 'text');
+          text.setAttribute('x', String(padL - 6));
+          text.setAttribute('y', String(y + 3));
+          text.setAttribute('text-anchor', 'end');
+          text.setAttribute('fill', 'var(--fg3)');
+          text.setAttribute('font-size', '9');
+          text.setAttribute('font-family', 'var(--mono)');
+          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
+          svg.appendChild(text);
+        }
+      }
+    });
+
+    // X-axis labels
+    data.forEach((s, i) => {
+      const x = padL + i * xStep;
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = (s.id || '').slice(0, 6);
+      svg.appendChild(text);
+    });
+
+    // Legend
+    const legendX = w - padR - this._metrics.length * 100;
+    this._metrics.forEach((m, i) => {
+      const x = legendX + i * 100;
+      const rect = document.createElementNS(svgNS, 'rect');
+      rect.setAttribute('x', x); rect.setAttribute('y', '4');
+      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
+      rect.setAttribute('rx', '2');
+      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
+      svg.appendChild(rect);
+
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = m.replace(/_/g, ' ');
+      svg.appendChild(text);
+    });
+  },
+
+  _renderSnapList(snaps) {
+    const el = document.getElementById('snapshot-list');
+    if (!el) return;
+    clearEl(el);
+    if (!snaps.length) {
+      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
+      return;
+    }
+    snaps.forEach((s, idx) => {
+      const healthPct = Number(s.health_score) || 0;
+      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
+      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
+
+      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
+      if (idx < snaps.length - 1) {
+        const prev = snaps[idx + 1];
+        const defs = [
+          { key: 'instruction_count', label: 'inst' },
+          { key: 'health_score', label: 'health' },
+          { key: 'unit_count', label: 'units' },
+        ];
+        defs.forEach(d => {
+          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
+          if (delta !== 0) {
+            const cls = delta > 0 ? 'positive' : 'negative';
+            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
+              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
+          }
+        });
+      }
+
+      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
+        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
+        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
+        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
+        deltas,
+        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
+        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
+          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
+      ));
+    });
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Insights View
+   ============================================================ */
+
+const insightEmptyReasons = {
+  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
+  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
+  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
+  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
+  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
+  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
+};
+
+const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
+
+const InsightsView = {
+  _running: new Set(),
+
+  async render() {
+    this._running = new Set();
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
+    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
+    container.appendChild(grid);
+    Shell.renderMain(container);
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const res = await API.insights(snap.id);
+    const insights = Array.isArray(res.data) ? res.data : [];
+
+    if (!insights.length) {
+      grid.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'No insights available'),
+        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
+      return;
+    }
+
+    const available = insights.filter(i => i.available);
+    const unavailable = insights.filter(i => !i.available);
+
+    if (available.length) {
+      available.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
+      });
+    }
+
+    if (unavailable.length) {
+      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
+      unavailable.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
+      });
+    }
+
+    available.forEach((insight, idx) => {
+      this._runInsight(insight, idx, snap.id);
+    });
+  },
+
+  _renderInsightCard(insight, idx, snapId) {
+    const category = CapabilityData.category(insight.required_capability || '');
+    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
+      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
+      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
+      h('div', { class: 'insight-desc' }, insight.description || '')
+    );
+
+    if (!insight.available) {
+      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
+      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return card;
+    }
+
+    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
+    body.appendChild(h('div', { class: 'insight-skeleton' }));
+    card.appendChild(body);
+    return card;
+  },
+
+  async _runInsight(insight, idx, snapId) {
+    if (this._running.has(insight.name)) return;
+    this._running.add(insight.name);
+
+    const body = document.getElementById(`insight-body-${idx}`);
+    if (!body) return;
+
+    let res = null;
+    if (insightNeedsBaseline.has(insight.name)) {
+      const snaps = State.get('snapshots') || [];
+      const curIdx = snaps.findIndex(s => s.id === snapId);
+      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
+        res = await API.insight(snapId, insight.name, snaps[i].id);
+      }
+      if (!res?.ok) res = await API.insight(snapId, insight.name);
+    } else {
+      res = await API.insight(snapId, insight.name);
+    }
+    clearEl(body);
+
+    if (!res.ok) {
+      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
+      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return;
+    }
+
+    const rawData = res.data?.data || res.data;
+    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
+      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
+        h('div', {}, 'No data to display'),
+        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
+      return;
+    }
+
+    const rendered = this._renderInsightData(insight.name, rawData);
+    if (rendered) {
+      body.appendChild(rendered);
+    } else {
+      const normalized = CapabilityData.normalizeResults([
+        { capability: insight.required_capability || insight.name, value: rawData }
+      ])[0];
+      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
+    }
+  },
+
+  _renderInsightData(name, data) {
+    const d = data || {};
+    const wrap = h('div', { class: 'insight-content' });
+
+    if (name === 'pass_impact') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
+      const byType = d.by_type || {};
+      Object.entries(byType).forEach(([k, v]) => {
+        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
+      });
+      wrap.appendChild(metrics);
+      if (d.by_type && Object.keys(d.by_type).length > 1) {
+        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
+        const donut = UI.donutChart(donutData, { size: 100 });
+        if (donut) wrap.appendChild(donut);
+      }
+      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'function_complexity') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
+      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'debug_info') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
+      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
+      wrap.appendChild(metrics);
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    if (name === 'section_sizes') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
+      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
+      wrap.appendChild(metrics);
+      const cats = d.category_breakdown || {};
+      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
+      if (catEntries.length) {
+        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
+        const flame = UI.flameBars(flameItems);
+        if (flame) wrap.appendChild(flame);
+        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
+        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
+        catEntries.forEach(([label, v], i) => {
+          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
+            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
+            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
+      if (sections.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
+        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      return wrap;
+    }
+
+    if (name === 'loop_nesting') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'diagnostic_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
+      wrap.appendChild(metrics);
+      const base = d.baseline || {};
+      const prim = d.primary || {};
+      if (base.errors != null || prim.errors != null) {
+        const items = [
+          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
+          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
+          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
+        ];
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
+      if (newDiags.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
+        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'optimization_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
+      wrap.appendChild(metrics);
+      const byType = d.by_type_delta || {};
+      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
+      if (cleanEntries.length) {
+        const items = cleanEntries.map(([label, v]) => ({
+          label: titleCase(label),
+          before: v?.baseline || 0,
+          after: v?.primary || 0,
+        }));
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'header_depth') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
+      wrap.appendChild(metrics);
+      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
+      if (chains.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
+        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
+      }
+      const most = Array.isArray(d.most_included) ? d.most_included : [];
+      if (most.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
+        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
+      }
+      if (!chains.length && !most.length && !d.max_depth) {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'call_frequency') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
+      wrap.appendChild(metrics);
+      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
+      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
+      if (fanIn.length && fanInHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
+        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      if (fanOut.length && fanOutHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
+        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
+      if (hubs.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
+        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
+      }
+      if (!fanInHasData && !fanOutHasData && fanOut.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
+        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'compilation_flow') {
+      const stages = Array.isArray(d.stages) ? d.stages : [];
+      const total = d.total_duration_ms || 0;
+      const slowest = d.slowest_event || {};
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' },
+        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
+      if (slowest.name) {
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Event'),
+          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Time'),
+          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
+      }
+      wrap.appendChild(metrics);
+      if (stages.length) {
+        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
+        // Stacked horizontal bar
+        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
+        stages.forEach(s => {
+          const pct = s.pct_of_total || 0;
+          if (pct <= 0) return;
+          const color = colors[s.stage] || '#9B7DB8';
+          const seg = h('div', {
+            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
+                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
+            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
+          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
+          bar.appendChild(seg);
+        });
+        wrap.appendChild(bar);
+        // Legend rows
+        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
+        stages.forEach(s => {
+          const color = colors[s.stage] || '#9B7DB8';
+          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
+            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
+            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
+            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
+            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      return wrap;
+    }
+
+    if (name === 'metric_trends') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
+      wrap.appendChild(metrics);
+      if (d.functions > 0 && d.instructions > 0) {
+        const donutData = [
+          { label: 'Functions', value: d.functions },
+          { label: 'Globals', value: d.globals || 0 },
+        ].filter(x => x.value > 0);
+        if (donutData.length > 1) {
+          const donut = UI.donutChart(donutData, { size: 90 });
+          if (donut) wrap.appendChild(donut);
+        }
+      }
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    return null;
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Remarks Explorer View
+   ============================================================ */
+
+const RemarksView = {
+  async render() {
+    const snap = State.get('currentSnapshot');
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Optimization Remarks Explorer'));
+    Shell.renderMain(container);
+
+    if (!snap) {
+      container.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const skeleton = h('div', { class: 'dashboard-skeleton', style: { padding: '24px', display: 'flex', flexDirection: 'column', gap: '24px' } },
+      h('div', { style: { height: '80px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' } },
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } })
+      )
+    );
+    container.appendChild(skeleton);
+
+    const [relRes, queryRes] = await Promise.all([
+      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary']),
+    ]);
+
+    if (skeleton.parentNode) skeleton.parentNode.removeChild(skeleton);
+
+    if (!relRes.ok && !queryRes.ok) {
+      container.appendChild(UI.errorCard(
+        'No remarks data available. Capture with llvm.remarks.summary enabled.',
+        () => this.render()
+      ));
+      return;
+    }
+
+    const rel = relRes.ok && relRes.data ? relRes.data : null;
+    const queryUnits = queryRes.ok && Array.isArray(queryRes.data) ? queryRes.data : [];
+
+    // Top-level summary from summary capability
+    const byPass = {}, byType = {};
+    let totalRemarks = 0;
+    queryUnits.forEach(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      results.filter(r => r.capability === 'llvm.remarks.summary').forEach(res => {
+        const v = res.value || {};
+        totalRemarks += Number(v.count || v.remark_count || 0);
+        if (v.by_pass) Object.entries(v.by_pass).forEach(([p, c]) => { byPass[p] = (byPass[p] || 0) + Number(c); });
+        if (v.by_type) Object.entries(v.by_type).forEach(([t, c]) => { byType[t] = (byType[t] || 0) + Number(c); });
+      });
+    });
+
+    // Header stat row
+    const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
+    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
+    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
+    container.appendChild(statRow);
+
+    const grid = h('div', { class: 'overview-grid', style: { marginTop: '0' } });
+
+    // Pass distribution bar chart
+    const passEntries = Object.entries(byPass).sort((a, b) => b[1] - a[1]);
+    if (passEntries.length) {
+      const passData = passEntries.slice(0, 12).map(([label, amount]) => ({ label, amount }));
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks by Pass'),
+        UI.barChart(passData)
+      );
+      grid.appendChild(section);
+    }
+
+    // Remark type donut
+    const typeEntries = Object.entries(byType).filter(([, v]) => v > 0);
+    if (typeEntries.length) {
+      const typeData = typeEntries.map(([label, value]) => ({
+        label: label.charAt(0).toUpperCase() + label.slice(1),
+        value,
+      }));
+      const donut = UI.donutChart(typeData);
+      if (donut) {
+        grid.appendChild(h('div', { class: 'chart-section' },
+          h('h3', {}, 'By Remark Type'),
+          donut
+        ));
+      }
+    }
+
+    // Per-unit remark distribution (long tail)
+    const unitRemarks = queryUnits.map(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      const rem = results.filter(r => r.capability === 'llvm.remarks.summary')
+        .reduce((s, r) => s + Number(r.value?.count || r.value?.remark_count || 0), 0);
+      return { unit_id: u.unit_id, source_path: u.source_path, remarks: rem };
+    }).filter(u => u.remarks > 0).sort((a, b) => b.remarks - a.remarks);
+
+    if (unitRemarks.length) {
+      const flameItems = unitRemarks.slice(0, 10).map(u => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        return { label: file, value: u.remarks };
+      });
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks per Unit (top 10)')
+      );
+      const flame = UI.flameBars(flameItems);
+      if (flame) section.appendChild(flame);
+      // Legend with links
+      const legend = h('div', { style: { marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px', fontSize: '11px' } });
+      const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4', '#5B8DB8', '#D4A574'];
+      unitRemarks.slice(0, 10).forEach((u, i) => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        legend.appendChild(h('span', {
+          style: { display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer' },
+          onClick: () => Router.navigate(`/units/${encodeURIComponent(u.unit_id)}?snapshot=${encodeURIComponent(snap.id)}`),
+        },
+          h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i], display: 'inline-block', flexShrink: '0' } }),
+          `${file}: ${formatNumber(u.remarks)}`
+        ));
+      });
+      section.appendChild(legend);
+      grid.appendChild(section);
+    }
+
+    container.appendChild(grid);
+
+    // Relational table — top (pass, name) tuples
+    if (rel && rel.columns && rel.strings) {
+      const { columns, strings } = rel;
+      const passes = strings.pass || [];
+      const names = strings.name || [];
+      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+
+      // Count (pass, name) tuples
+      const tuples = {};
+      const passCols = columns.pass || [];
+      const nameCols = columns.name || [];
+      const typeCols = columns.type || [];
+      for (let i = 0; i < passCols.length; i++) {
+        const p = passes[passCols[i]] || '?';
+        const n = names[nameCols[i]] || '?';
+        const key = `${p}\0${n}`;
+        if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
+        const typeName = types[typeCols[i]] || 'unknown';
+        tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
+        tuples[key].count = (tuples[key].count || 0) + 1;
+      }
+
+      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      if (sorted.length) {
+        const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
+          h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
+        );
+        const table = h('table', { class: 'top-units-table' },
+          h('thead', {}, h('tr', {},
+            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+            h('th', { style: { textAlign: 'right' } }, 'Count'),
+            h('th', { style: { textAlign: 'right' } }, 'Missed'),
+            h('th', { style: { textAlign: 'right' } }, 'Passed'),
+          ))
+        );
+        const tbody = h('tbody', {});
+        sorted.forEach(t => {
+          tbody.appendChild(h('tr', {},
+            h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
+            h('td', { style: { fontSize: '11px' } }, t.name),
+            h('td', { class: 'num' }, formatNumber(t.count)),
+            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
+              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
+            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
+              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+          ));
+        });
+        table.appendChild(tbody);
+        tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
+        container.appendChild(tableSection);
+      }
+    }
+  },
+};
+
 /* ============================================================
    LLVM Advisor — Settings View
    ============================================================ */
@@ -3808,6 +4786,8 @@
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
+      Router.register('/timeline', () => TimelineView.render());
+      Router.register('/insights', () => InsightsView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index 021e98f40ee9f..7acb09c8d136d 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -8,6 +8,9 @@ const Icons = {
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
+  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
+  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
+  remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -107,6 +110,12 @@ const API = {
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
+  insight: (snapId, name, baseline) => {
+    let url = `/snapshots/${snapId}/insights/${name}`;
+    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
+    return API.get(url);
+  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
@@ -212,7 +221,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
index f28896e97fc90..ed7007aeb6896 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
@@ -24,6 +24,9 @@
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
+      Router.register('/timeline', () => TimelineView.render());
+      Router.register('/insights', () => InsightsView.render());
+      Router.register('/remarks', () => RemarksView.render());
       Router.register('/settings', () => SettingsView.render());
 
       Shell.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 690099eb81ee7..69d57f31b979a 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -692,6 +692,9 @@ const Icons = {
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
+  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
+  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
+  remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -791,6 +794,12 @@ const API = {
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
+  insight: (snapId, name, baseline) => {
+    let url = `/snapshots/${snapId}/insights/${name}`;
+    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
+    return API.get(url);
+  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
@@ -896,7 +905,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2018,6 +2027,9 @@ const Shell = {
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
+      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
+      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
+      { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2142,6 +2154,9 @@ const CommandPalette = {
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
+    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
+    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
+    { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -2261,7 +2276,10 @@ const OverviewView = {
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
+    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
+                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail',
+                      'llvm.debug.summary', 'clang.ast.summary',
+                      'llvm.lto.summary', 'llvm.lto.function_stats'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
@@ -3063,7 +3081,7 @@ const UnitDetailView = {
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Remarks', 'Artifacts'];
+    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -3124,7 +3142,19 @@ const UnitDetailView = {
 
     const controls = h('div', { class: 'cap-pills' });
     const body = h('div', { class: 'capability-stack' });
-    const modes = [['remarks', 'Remarks']];
+    const modes = [
+      ['signals', 'Signals'],
+      ['ir', 'IR'],
+      ['cfg', 'CFG'],
+      ['dom', 'Dom'],
+      ['loop', 'Loops'],
+      ['callgraph', 'Call Graph'],
+      ['asm', 'Asm'],
+      ['mca', 'MCA'],
+      ['remarks', 'Remarks'],
+      ['debug', 'Debug'],
+      ['passes', 'Passes'],
+    ];
 
     const loadMode = async (mode, pill) => {
       Array.from(controls.children).forEach(node => node.classList.remove('available'));
@@ -3179,6 +3209,10 @@ const UnitDetailView = {
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
     // Function list placeholder in sidebar
+    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
+      h('div', { class: 'rail-title' }, 'Functions'),
+      h('div', { class: 'rail-empty' }, 'Loading function list')
+    ));
   },
 
   addSection(parent, title, open, kvPairs) {
@@ -3204,6 +3238,20 @@ const UnitDetailView = {
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
+    if (tab === 'Diagnostics') {
+      const findings = state.results
+        .filter(r => r.capability.startsWith('clang.diag'))
+        .flatMap(r => r.findings);
+      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
+      const bySev = {};
+      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
+      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
+      return h('div', { class: 'capability-stack' },
+        chartData.length ? UI.barChart(chartData) : null,
+        UI.findingList(findings)
+      );
+    }
+
     if (tab === 'Remarks') {
       const findings = state.results
         .filter(r => r.capability.includes('remarks'))
@@ -3217,6 +3265,13 @@ const UnitDetailView = {
       );
     }
 
+    if (tab === 'Functions') {
+      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
+      const rows = fnResult?.value?.functions || [];
+      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
+      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
+    }
+
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -3234,6 +3289,9 @@ const UnitDetailView = {
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
+        this.summaryCard('Functions', metrics.functions, 'neutral'),
+        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
+        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -3257,9 +3315,12 @@ const UnitDetailView = {
   },
 
   collectOverview(results) {
-    const metrics = { remarks: 0 };
+    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
+      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
+      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
+      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -3269,7 +3330,7 @@ const UnitDetailView = {
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['llvm.remarks.summary', 'llvm.remarks.detail'];
+      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -3281,6 +3342,30 @@ const UnitDetailView = {
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
+    // Populate function list in sidebar
+    const fnCard = sidebar.querySelector('#function-list-card');
+    results.forEach(r => {
+      const val = r.value;
+      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
+        if (fnCard) {
+          clearEl(fnCard);
+          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
+          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
+          const list = h('div', { class: 'fn-section' });
+          fns.slice(0, 50).forEach(fn => {
+            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
+              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
+              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
+            ));
+          });
+          if (fns.length > 50) {
+            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
+              `+ ${fns.length - 50} more…`));
+          }
+          fnCard.appendChild(list);
+        }
+      }
+    });
     if (refresh) refresh();
   },
 
@@ -3607,6 +3692,899 @@ const CompareView = {
 
   </script>
   <script>
+/* ============================================================
+   LLVM Advisor — Timeline View
+   ============================================================ */
+
+const TimelineView = {
+  _metrics: ['unit_count', 'instruction_count', 'health_score'],
+  _colors: {
+    unit_count: '#5B8DB8',
+    instruction_count: '#5DB8A8',
+    health_score: '#6EC9C4',
+    warning_count: '#D4A574',
+    error_count: '#D48B9B',
+  },
+  _snapData: [],
+
+  async render() {
+    const container = h('div', {});
+
+    const chips = h('div', { class: 'metric-chips' });
+    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
+      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
+      const chip = h('div', {
+        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
+        onClick: () => {
+          const idx = this._metrics.indexOf(m);
+          if (idx >= 0) this._metrics.splice(idx, 1);
+          else if (this._metrics.length < 4) this._metrics.push(m);
+          chip.classList.toggle('active');
+          this._drawChart();
+        },
+      },
+        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
+        label
+      );
+      chips.appendChild(chip);
+    });
+    container.appendChild(chips);
+
+    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
+
+    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
+
+    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
+    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
+
+    Shell.renderMain(container);
+    await this._loadData();
+  },
+
+  async _loadData() {
+    const snaps = State.get('snapshots') || [];
+    if (!snaps.length) {
+      this._renderSnapList([]);
+      return;
+    }
+
+    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
+    this._snapData = snaps.map((s, i) => {
+      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
+      return {
+        ...s,
+        unit_count: sum.unit_count ?? s.unit_count ?? 0,
+        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
+        health_score: sum.health_score ?? 0,
+        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
+        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
+        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
+        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
+      };
+    });
+
+    this._renderSnapList(this._snapData);
+    this._renderMetricCards();
+    this._drawChart();
+  },
+
+  _renderMetricCards() {
+    const el = document.getElementById('timeline-metrics');
+    if (!el || !this._snapData.length) return;
+    clearEl(el);
+    const latest = this._snapData[0];
+    const metricDefs = [
+      { key: 'unit_count', label: 'Units' },
+      { key: 'instruction_count', label: 'Instructions' },
+      { key: 'health_score', label: 'Health' },
+      { key: 'remark_count', label: 'Remarks' },
+      { key: 'function_count', label: 'Functions' },
+    ];
+    metricDefs.forEach(m => {
+      const val = latest[m.key] ?? 0;
+      let delta = null, deltaCls = 'neutral';
+      if (this._snapData.length > 1) {
+        const prev = this._snapData[1];
+        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
+        if (d !== 0) {
+          const sign = d > 0 ? '+' : '';
+          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
+          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
+          delta = `${sign}${formatNumber(d)} vs prev`;
+        }
+      }
+      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
+    });
+  },
+
+  _drawChart() {
+    const container = document.getElementById('timeline-chart-container');
+    if (!container) return;
+    clearEl(container);
+    const data = this._snapData;
+    const svgNS = 'http://www.w3.org/2000/svg';
+    const svg = document.createElementNS(svgNS, 'svg');
+    svg.style.width = '100%';
+    svg.style.height = '220px';
+    container.appendChild(svg);
+
+    if (data.length < 2) {
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
+      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
+      svg.appendChild(text);
+      return;
+    }
+
+    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
+    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
+    const chartW = w - padL - padR;
+    const chartH = ht - padT - padB;
+
+    // Horizontal grid lines
+    for (let i = 0; i <= 4; i++) {
+      const y = padT + (chartH * i / 4);
+      const line = document.createElementNS(svgNS, 'line');
+      line.setAttribute('x1', padL); line.setAttribute('y1', y);
+      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
+      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
+      line.setAttribute('stroke-width', '1');
+      svg.appendChild(line);
+    }
+
+    const xStep = chartW / (data.length - 1);
+
+    this._metrics.forEach(m => {
+      const values = data.map(s => Number(s[m]) || 0);
+      const max = Math.max(...values, 1);
+      const min = Math.min(...values, 0);
+      const range = max - min || 1;
+      const color = this._colors[m] || 'var(--accent)';
+
+      const points = data.map((_, i) => {
+        const x = padL + i * xStep;
+        const y = padT + chartH - ((values[i] - min) / range) * chartH;
+        return `${x.toFixed(1)},${y.toFixed(1)}`;
+      });
+
+      // Area fill
+      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
+      const area = document.createElementNS(svgNS, 'polygon');
+      area.setAttribute('points', areaPoints);
+      area.setAttribute('fill', color);
+      area.setAttribute('opacity', '0.08');
+      svg.appendChild(area);
+
+      const poly = document.createElementNS(svgNS, 'polyline');
+      poly.setAttribute('points', points.join(' '));
+      poly.setAttribute('fill', 'none');
+      poly.setAttribute('stroke', color);
+      poly.setAttribute('stroke-width', '2');
+      poly.setAttribute('stroke-linejoin', 'round');
+      svg.appendChild(poly);
+
+      data.forEach((_, i) => {
+        const [x, y] = points[i].split(',');
+        const circle = document.createElementNS(svgNS, 'circle');
+        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
+        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
+        svg.appendChild(circle);
+      });
+
+      // Y-axis labels for first metric only
+      if (m === this._metrics[0]) {
+        for (let i = 0; i <= 4; i++) {
+          const val = min + (range * (4 - i) / 4);
+          const y = padT + (chartH * i / 4);
+          const text = document.createElementNS(svgNS, 'text');
+          text.setAttribute('x', String(padL - 6));
+          text.setAttribute('y', String(y + 3));
+          text.setAttribute('text-anchor', 'end');
+          text.setAttribute('fill', 'var(--fg3)');
+          text.setAttribute('font-size', '9');
+          text.setAttribute('font-family', 'var(--mono)');
+          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
+          svg.appendChild(text);
+        }
+      }
+    });
+
+    // X-axis labels
+    data.forEach((s, i) => {
+      const x = padL + i * xStep;
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = (s.id || '').slice(0, 6);
+      svg.appendChild(text);
+    });
+
+    // Legend
+    const legendX = w - padR - this._metrics.length * 100;
+    this._metrics.forEach((m, i) => {
+      const x = legendX + i * 100;
+      const rect = document.createElementNS(svgNS, 'rect');
+      rect.setAttribute('x', x); rect.setAttribute('y', '4');
+      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
+      rect.setAttribute('rx', '2');
+      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
+      svg.appendChild(rect);
+
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = m.replace(/_/g, ' ');
+      svg.appendChild(text);
+    });
+  },
+
+  _renderSnapList(snaps) {
+    const el = document.getElementById('snapshot-list');
+    if (!el) return;
+    clearEl(el);
+    if (!snaps.length) {
+      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
+      return;
+    }
+    snaps.forEach((s, idx) => {
+      const healthPct = Number(s.health_score) || 0;
+      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
+      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
+
+      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
+      if (idx < snaps.length - 1) {
+        const prev = snaps[idx + 1];
+        const defs = [
+          { key: 'instruction_count', label: 'inst' },
+          { key: 'health_score', label: 'health' },
+          { key: 'unit_count', label: 'units' },
+        ];
+        defs.forEach(d => {
+          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
+          if (delta !== 0) {
+            const cls = delta > 0 ? 'positive' : 'negative';
+            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
+              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
+          }
+        });
+      }
+
+      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
+        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
+        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
+        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
+        deltas,
+        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
+        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
+          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
+      ));
+    });
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Insights View
+   ============================================================ */
+
+const insightEmptyReasons = {
+  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
+  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
+  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
+  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
+  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
+  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
+};
+
+const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
+
+const InsightsView = {
+  _running: new Set(),
+
+  async render() {
+    this._running = new Set();
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
+    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
+    container.appendChild(grid);
+    Shell.renderMain(container);
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const res = await API.insights(snap.id);
+    const insights = Array.isArray(res.data) ? res.data : [];
+
+    if (!insights.length) {
+      grid.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'No insights available'),
+        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
+      return;
+    }
+
+    const available = insights.filter(i => i.available);
+    const unavailable = insights.filter(i => !i.available);
+
+    if (available.length) {
+      available.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
+      });
+    }
+
+    if (unavailable.length) {
+      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
+      unavailable.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
+      });
+    }
+
+    available.forEach((insight, idx) => {
+      this._runInsight(insight, idx, snap.id);
+    });
+  },
+
+  _renderInsightCard(insight, idx, snapId) {
+    const category = CapabilityData.category(insight.required_capability || '');
+    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
+      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
+      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
+      h('div', { class: 'insight-desc' }, insight.description || '')
+    );
+
+    if (!insight.available) {
+      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
+      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return card;
+    }
+
+    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
+    body.appendChild(h('div', { class: 'insight-skeleton' }));
+    card.appendChild(body);
+    return card;
+  },
+
+  async _runInsight(insight, idx, snapId) {
+    if (this._running.has(insight.name)) return;
+    this._running.add(insight.name);
+
+    const body = document.getElementById(`insight-body-${idx}`);
+    if (!body) return;
+
+    let res = null;
+    if (insightNeedsBaseline.has(insight.name)) {
+      const snaps = State.get('snapshots') || [];
+      const curIdx = snaps.findIndex(s => s.id === snapId);
+      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
+        res = await API.insight(snapId, insight.name, snaps[i].id);
+      }
+      if (!res?.ok) res = await API.insight(snapId, insight.name);
+    } else {
+      res = await API.insight(snapId, insight.name);
+    }
+    clearEl(body);
+
+    if (!res.ok) {
+      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
+      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return;
+    }
+
+    const rawData = res.data?.data || res.data;
+    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
+      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
+        h('div', {}, 'No data to display'),
+        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
+      return;
+    }
+
+    const rendered = this._renderInsightData(insight.name, rawData);
+    if (rendered) {
+      body.appendChild(rendered);
+    } else {
+      const normalized = CapabilityData.normalizeResults([
+        { capability: insight.required_capability || insight.name, value: rawData }
+      ])[0];
+      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
+    }
+  },
+
+  _renderInsightData(name, data) {
+    const d = data || {};
+    const wrap = h('div', { class: 'insight-content' });
+
+    if (name === 'pass_impact') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
+      const byType = d.by_type || {};
+      Object.entries(byType).forEach(([k, v]) => {
+        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
+      });
+      wrap.appendChild(metrics);
+      if (d.by_type && Object.keys(d.by_type).length > 1) {
+        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
+        const donut = UI.donutChart(donutData, { size: 100 });
+        if (donut) wrap.appendChild(donut);
+      }
+      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'function_complexity') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
+      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'debug_info') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
+      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
+      wrap.appendChild(metrics);
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    if (name === 'section_sizes') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
+      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
+      wrap.appendChild(metrics);
+      const cats = d.category_breakdown || {};
+      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
+      if (catEntries.length) {
+        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
+        const flame = UI.flameBars(flameItems);
+        if (flame) wrap.appendChild(flame);
+        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
+        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
+        catEntries.forEach(([label, v], i) => {
+          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
+            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
+            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
+      if (sections.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
+        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      return wrap;
+    }
+
+    if (name === 'loop_nesting') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'diagnostic_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
+      wrap.appendChild(metrics);
+      const base = d.baseline || {};
+      const prim = d.primary || {};
+      if (base.errors != null || prim.errors != null) {
+        const items = [
+          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
+          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
+          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
+        ];
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
+      if (newDiags.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
+        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'optimization_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
+      wrap.appendChild(metrics);
+      const byType = d.by_type_delta || {};
+      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
+      if (cleanEntries.length) {
+        const items = cleanEntries.map(([label, v]) => ({
+          label: titleCase(label),
+          before: v?.baseline || 0,
+          after: v?.primary || 0,
+        }));
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'header_depth') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
+      wrap.appendChild(metrics);
+      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
+      if (chains.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
+        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
+      }
+      const most = Array.isArray(d.most_included) ? d.most_included : [];
+      if (most.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
+        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
+      }
+      if (!chains.length && !most.length && !d.max_depth) {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'call_frequency') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
+      wrap.appendChild(metrics);
+      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
+      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
+      if (fanIn.length && fanInHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
+        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      if (fanOut.length && fanOutHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
+        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
+      if (hubs.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
+        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
+      }
+      if (!fanInHasData && !fanOutHasData && fanOut.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
+        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'compilation_flow') {
+      const stages = Array.isArray(d.stages) ? d.stages : [];
+      const total = d.total_duration_ms || 0;
+      const slowest = d.slowest_event || {};
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' },
+        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
+      if (slowest.name) {
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Event'),
+          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Time'),
+          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
+      }
+      wrap.appendChild(metrics);
+      if (stages.length) {
+        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
+        // Stacked horizontal bar
+        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
+        stages.forEach(s => {
+          const pct = s.pct_of_total || 0;
+          if (pct <= 0) return;
+          const color = colors[s.stage] || '#9B7DB8';
+          const seg = h('div', {
+            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
+                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
+            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
+          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
+          bar.appendChild(seg);
+        });
+        wrap.appendChild(bar);
+        // Legend rows
+        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
+        stages.forEach(s => {
+          const color = colors[s.stage] || '#9B7DB8';
+          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
+            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
+            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
+            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
+            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      return wrap;
+    }
+
+    if (name === 'metric_trends') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
+      wrap.appendChild(metrics);
+      if (d.functions > 0 && d.instructions > 0) {
+        const donutData = [
+          { label: 'Functions', value: d.functions },
+          { label: 'Globals', value: d.globals || 0 },
+        ].filter(x => x.value > 0);
+        if (donutData.length > 1) {
+          const donut = UI.donutChart(donutData, { size: 90 });
+          if (donut) wrap.appendChild(donut);
+        }
+      }
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    return null;
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Remarks Explorer View
+   ============================================================ */
+
+const RemarksView = {
+  async render() {
+    const snap = State.get('currentSnapshot');
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Optimization Remarks Explorer'));
+    Shell.renderMain(container);
+
+    if (!snap) {
+      container.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const skeleton = h('div', { class: 'dashboard-skeleton', style: { padding: '24px', display: 'flex', flexDirection: 'column', gap: '24px' } },
+      h('div', { style: { height: '80px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' } },
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } })
+      )
+    );
+    container.appendChild(skeleton);
+
+    const [relRes, queryRes] = await Promise.all([
+      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary']),
+    ]);
+
+    if (skeleton.parentNode) skeleton.parentNode.removeChild(skeleton);
+
+    if (!relRes.ok && !queryRes.ok) {
+      container.appendChild(UI.errorCard(
+        'No remarks data available. Capture with llvm.remarks.summary enabled.',
+        () => this.render()
+      ));
+      return;
+    }
+
+    const rel = relRes.ok && relRes.data ? relRes.data : null;
+    const queryUnits = queryRes.ok && Array.isArray(queryRes.data) ? queryRes.data : [];
+
+    // Top-level summary from summary capability
+    const byPass = {}, byType = {};
+    let totalRemarks = 0;
+    queryUnits.forEach(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      results.filter(r => r.capability === 'llvm.remarks.summary').forEach(res => {
+        const v = res.value || {};
+        totalRemarks += Number(v.count || v.remark_count || 0);
+        if (v.by_pass) Object.entries(v.by_pass).forEach(([p, c]) => { byPass[p] = (byPass[p] || 0) + Number(c); });
+        if (v.by_type) Object.entries(v.by_type).forEach(([t, c]) => { byType[t] = (byType[t] || 0) + Number(c); });
+      });
+    });
+
+    // Header stat row
+    const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
+    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
+    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
+    container.appendChild(statRow);
+
+    const grid = h('div', { class: 'overview-grid', style: { marginTop: '0' } });
+
+    // Pass distribution bar chart
+    const passEntries = Object.entries(byPass).sort((a, b) => b[1] - a[1]);
+    if (passEntries.length) {
+      const passData = passEntries.slice(0, 12).map(([label, amount]) => ({ label, amount }));
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks by Pass'),
+        UI.barChart(passData)
+      );
+      grid.appendChild(section);
+    }
+
+    // Remark type donut
+    const typeEntries = Object.entries(byType).filter(([, v]) => v > 0);
+    if (typeEntries.length) {
+      const typeData = typeEntries.map(([label, value]) => ({
+        label: label.charAt(0).toUpperCase() + label.slice(1),
+        value,
+      }));
+      const donut = UI.donutChart(typeData);
+      if (donut) {
+        grid.appendChild(h('div', { class: 'chart-section' },
+          h('h3', {}, 'By Remark Type'),
+          donut
+        ));
+      }
+    }
+
+    // Per-unit remark distribution (long tail)
+    const unitRemarks = queryUnits.map(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      const rem = results.filter(r => r.capability === 'llvm.remarks.summary')
+        .reduce((s, r) => s + Number(r.value?.count || r.value?.remark_count || 0), 0);
+      return { unit_id: u.unit_id, source_path: u.source_path, remarks: rem };
+    }).filter(u => u.remarks > 0).sort((a, b) => b.remarks - a.remarks);
+
+    if (unitRemarks.length) {
+      const flameItems = unitRemarks.slice(0, 10).map(u => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        return { label: file, value: u.remarks };
+      });
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks per Unit (top 10)')
+      );
+      const flame = UI.flameBars(flameItems);
+      if (flame) section.appendChild(flame);
+      // Legend with links
+      const legend = h('div', { style: { marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px', fontSize: '11px' } });
+      const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4', '#5B8DB8', '#D4A574'];
+      unitRemarks.slice(0, 10).forEach((u, i) => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        legend.appendChild(h('span', {
+          style: { display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer' },
+          onClick: () => Router.navigate(`/units/${encodeURIComponent(u.unit_id)}?snapshot=${encodeURIComponent(snap.id)}`),
+        },
+          h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i], display: 'inline-block', flexShrink: '0' } }),
+          `${file}: ${formatNumber(u.remarks)}`
+        ));
+      });
+      section.appendChild(legend);
+      grid.appendChild(section);
+    }
+
+    container.appendChild(grid);
+
+    // Relational table — top (pass, name) tuples
+    if (rel && rel.columns && rel.strings) {
+      const { columns, strings } = rel;
+      const passes = strings.pass || [];
+      const names = strings.name || [];
+      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+
+      // Count (pass, name) tuples
+      const tuples = {};
+      const passCols = columns.pass || [];
+      const nameCols = columns.name || [];
+      const typeCols = columns.type || [];
+      for (let i = 0; i < passCols.length; i++) {
+        const p = passes[passCols[i]] || '?';
+        const n = names[nameCols[i]] || '?';
+        const key = `${p}\0${n}`;
+        if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
+        const typeName = types[typeCols[i]] || 'unknown';
+        tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
+        tuples[key].count = (tuples[key].count || 0) + 1;
+      }
+
+      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      if (sorted.length) {
+        const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
+          h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
+        );
+        const table = h('table', { class: 'top-units-table' },
+          h('thead', {}, h('tr', {},
+            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+            h('th', { style: { textAlign: 'right' } }, 'Count'),
+            h('th', { style: { textAlign: 'right' } }, 'Missed'),
+            h('th', { style: { textAlign: 'right' } }, 'Passed'),
+          ))
+        );
+        const tbody = h('tbody', {});
+        sorted.forEach(t => {
+          tbody.appendChild(h('tr', {},
+            h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
+            h('td', { style: { fontSize: '11px' } }, t.name),
+            h('td', { class: 'num' }, formatNumber(t.count)),
+            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
+              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
+            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
+              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+          ));
+        });
+        table.appendChild(tbody);
+        tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
+        container.appendChild(tableSection);
+      }
+    }
+  },
+};
+
 /* ============================================================
    LLVM Advisor — Settings View
    ============================================================ */
@@ -3811,6 +4789,8 @@ const SettingsView = {
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
+      Router.register('/timeline', () => TimelineView.render());
+      Router.register('/insights', () => InsightsView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
index 033f61b9311e8..7ad33b4065b0b 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
@@ -75,6 +75,9 @@ const Shell = {
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
+      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
+      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
+      { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -199,6 +202,9 @@ const CommandPalette = {
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
+    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
+    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
+    { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index a88bffbecc34b..b98bbed150b3f 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1,3 +1,896 @@
+/* ============================================================
+   LLVM Advisor — Timeline View
+   ============================================================ */
+
+const TimelineView = {
+  _metrics: ['unit_count', 'instruction_count', 'health_score'],
+  _colors: {
+    unit_count: '#5B8DB8',
+    instruction_count: '#5DB8A8',
+    health_score: '#6EC9C4',
+    warning_count: '#D4A574',
+    error_count: '#D48B9B',
+  },
+  _snapData: [],
+
+  async render() {
+    const container = h('div', {});
+
+    const chips = h('div', { class: 'metric-chips' });
+    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
+      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
+      const chip = h('div', {
+        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
+        onClick: () => {
+          const idx = this._metrics.indexOf(m);
+          if (idx >= 0) this._metrics.splice(idx, 1);
+          else if (this._metrics.length < 4) this._metrics.push(m);
+          chip.classList.toggle('active');
+          this._drawChart();
+        },
+      },
+        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
+        label
+      );
+      chips.appendChild(chip);
+    });
+    container.appendChild(chips);
+
+    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
+
+    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
+
+    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
+    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
+
+    Shell.renderMain(container);
+    await this._loadData();
+  },
+
+  async _loadData() {
+    const snaps = State.get('snapshots') || [];
+    if (!snaps.length) {
+      this._renderSnapList([]);
+      return;
+    }
+
+    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
+    this._snapData = snaps.map((s, i) => {
+      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
+      return {
+        ...s,
+        unit_count: sum.unit_count ?? s.unit_count ?? 0,
+        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
+        health_score: sum.health_score ?? 0,
+        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
+        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
+        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
+        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
+      };
+    });
+
+    this._renderSnapList(this._snapData);
+    this._renderMetricCards();
+    this._drawChart();
+  },
+
+  _renderMetricCards() {
+    const el = document.getElementById('timeline-metrics');
+    if (!el || !this._snapData.length) return;
+    clearEl(el);
+    const latest = this._snapData[0];
+    const metricDefs = [
+      { key: 'unit_count', label: 'Units' },
+      { key: 'instruction_count', label: 'Instructions' },
+      { key: 'health_score', label: 'Health' },
+      { key: 'remark_count', label: 'Remarks' },
+      { key: 'function_count', label: 'Functions' },
+    ];
+    metricDefs.forEach(m => {
+      const val = latest[m.key] ?? 0;
+      let delta = null, deltaCls = 'neutral';
+      if (this._snapData.length > 1) {
+        const prev = this._snapData[1];
+        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
+        if (d !== 0) {
+          const sign = d > 0 ? '+' : '';
+          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
+          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
+          delta = `${sign}${formatNumber(d)} vs prev`;
+        }
+      }
+      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
+    });
+  },
+
+  _drawChart() {
+    const container = document.getElementById('timeline-chart-container');
+    if (!container) return;
+    clearEl(container);
+    const data = this._snapData;
+    const svgNS = 'http://www.w3.org/2000/svg';
+    const svg = document.createElementNS(svgNS, 'svg');
+    svg.style.width = '100%';
+    svg.style.height = '220px';
+    container.appendChild(svg);
+
+    if (data.length < 2) {
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
+      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
+      svg.appendChild(text);
+      return;
+    }
+
+    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
+    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
+    const chartW = w - padL - padR;
+    const chartH = ht - padT - padB;
+
+    // Horizontal grid lines
+    for (let i = 0; i <= 4; i++) {
+      const y = padT + (chartH * i / 4);
+      const line = document.createElementNS(svgNS, 'line');
+      line.setAttribute('x1', padL); line.setAttribute('y1', y);
+      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
+      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
+      line.setAttribute('stroke-width', '1');
+      svg.appendChild(line);
+    }
+
+    const xStep = chartW / (data.length - 1);
+
+    this._metrics.forEach(m => {
+      const values = data.map(s => Number(s[m]) || 0);
+      const max = Math.max(...values, 1);
+      const min = Math.min(...values, 0);
+      const range = max - min || 1;
+      const color = this._colors[m] || 'var(--accent)';
+
+      const points = data.map((_, i) => {
+        const x = padL + i * xStep;
+        const y = padT + chartH - ((values[i] - min) / range) * chartH;
+        return `${x.toFixed(1)},${y.toFixed(1)}`;
+      });
+
+      // Area fill
+      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
+      const area = document.createElementNS(svgNS, 'polygon');
+      area.setAttribute('points', areaPoints);
+      area.setAttribute('fill', color);
+      area.setAttribute('opacity', '0.08');
+      svg.appendChild(area);
+
+      const poly = document.createElementNS(svgNS, 'polyline');
+      poly.setAttribute('points', points.join(' '));
+      poly.setAttribute('fill', 'none');
+      poly.setAttribute('stroke', color);
+      poly.setAttribute('stroke-width', '2');
+      poly.setAttribute('stroke-linejoin', 'round');
+      svg.appendChild(poly);
+
+      data.forEach((_, i) => {
+        const [x, y] = points[i].split(',');
+        const circle = document.createElementNS(svgNS, 'circle');
+        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
+        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
+        svg.appendChild(circle);
+      });
+
+      // Y-axis labels for first metric only
+      if (m === this._metrics[0]) {
+        for (let i = 0; i <= 4; i++) {
+          const val = min + (range * (4 - i) / 4);
+          const y = padT + (chartH * i / 4);
+          const text = document.createElementNS(svgNS, 'text');
+          text.setAttribute('x', String(padL - 6));
+          text.setAttribute('y', String(y + 3));
+          text.setAttribute('text-anchor', 'end');
+          text.setAttribute('fill', 'var(--fg3)');
+          text.setAttribute('font-size', '9');
+          text.setAttribute('font-family', 'var(--mono)');
+          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
+          svg.appendChild(text);
+        }
+      }
+    });
+
+    // X-axis labels
+    data.forEach((s, i) => {
+      const x = padL + i * xStep;
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
+      text.setAttribute('text-anchor', 'middle');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = (s.id || '').slice(0, 6);
+      svg.appendChild(text);
+    });
+
+    // Legend
+    const legendX = w - padR - this._metrics.length * 100;
+    this._metrics.forEach((m, i) => {
+      const x = legendX + i * 100;
+      const rect = document.createElementNS(svgNS, 'rect');
+      rect.setAttribute('x', x); rect.setAttribute('y', '4');
+      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
+      rect.setAttribute('rx', '2');
+      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
+      svg.appendChild(rect);
+
+      const text = document.createElementNS(svgNS, 'text');
+      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
+      text.setAttribute('fill', 'var(--fg3)');
+      text.setAttribute('font-size', '9');
+      text.setAttribute('font-family', 'var(--mono)');
+      text.textContent = m.replace(/_/g, ' ');
+      svg.appendChild(text);
+    });
+  },
+
+  _renderSnapList(snaps) {
+    const el = document.getElementById('snapshot-list');
+    if (!el) return;
+    clearEl(el);
+    if (!snaps.length) {
+      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
+      return;
+    }
+    snaps.forEach((s, idx) => {
+      const healthPct = Number(s.health_score) || 0;
+      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
+      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
+
+      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
+      if (idx < snaps.length - 1) {
+        const prev = snaps[idx + 1];
+        const defs = [
+          { key: 'instruction_count', label: 'inst' },
+          { key: 'health_score', label: 'health' },
+          { key: 'unit_count', label: 'units' },
+        ];
+        defs.forEach(d => {
+          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
+          if (delta !== 0) {
+            const cls = delta > 0 ? 'positive' : 'negative';
+            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
+              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
+          }
+        });
+      }
+
+      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
+        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
+        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
+        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
+        deltas,
+        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
+        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
+          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
+      ));
+    });
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Insights View
+   ============================================================ */
+
+const insightEmptyReasons = {
+  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
+  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
+  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
+  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
+  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
+  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
+};
+
+const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
+
+const InsightsView = {
+  _running: new Set(),
+
+  async render() {
+    this._running = new Set();
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
+    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
+    container.appendChild(grid);
+    Shell.renderMain(container);
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const res = await API.insights(snap.id);
+    const insights = Array.isArray(res.data) ? res.data : [];
+
+    if (!insights.length) {
+      grid.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'No insights available'),
+        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
+      return;
+    }
+
+    const available = insights.filter(i => i.available);
+    const unavailable = insights.filter(i => !i.available);
+
+    if (available.length) {
+      available.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
+      });
+    }
+
+    if (unavailable.length) {
+      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
+      unavailable.forEach((insight, idx) => {
+        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
+      });
+    }
+
+    available.forEach((insight, idx) => {
+      this._runInsight(insight, idx, snap.id);
+    });
+  },
+
+  _renderInsightCard(insight, idx, snapId) {
+    const category = CapabilityData.category(insight.required_capability || '');
+    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
+      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
+      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
+      h('div', { class: 'insight-desc' }, insight.description || '')
+    );
+
+    if (!insight.available) {
+      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
+      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return card;
+    }
+
+    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
+    body.appendChild(h('div', { class: 'insight-skeleton' }));
+    card.appendChild(body);
+    return card;
+  },
+
+  async _runInsight(insight, idx, snapId) {
+    if (this._running.has(insight.name)) return;
+    this._running.add(insight.name);
+
+    const body = document.getElementById(`insight-body-${idx}`);
+    if (!body) return;
+
+    let res = null;
+    if (insightNeedsBaseline.has(insight.name)) {
+      const snaps = State.get('snapshots') || [];
+      const curIdx = snaps.findIndex(s => s.id === snapId);
+      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
+        res = await API.insight(snapId, insight.name, snaps[i].id);
+      }
+      if (!res?.ok) res = await API.insight(snapId, insight.name);
+    } else {
+      res = await API.insight(snapId, insight.name);
+    }
+    clearEl(body);
+
+    if (!res.ok) {
+      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
+      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
+        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
+        reason
+      ));
+      return;
+    }
+
+    const rawData = res.data?.data || res.data;
+    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
+      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
+        h('div', {}, 'No data to display'),
+        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
+      return;
+    }
+
+    const rendered = this._renderInsightData(insight.name, rawData);
+    if (rendered) {
+      body.appendChild(rendered);
+    } else {
+      const normalized = CapabilityData.normalizeResults([
+        { capability: insight.required_capability || insight.name, value: rawData }
+      ])[0];
+      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
+    }
+  },
+
+  _renderInsightData(name, data) {
+    const d = data || {};
+    const wrap = h('div', { class: 'insight-content' });
+
+    if (name === 'pass_impact') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
+      const byType = d.by_type || {};
+      Object.entries(byType).forEach(([k, v]) => {
+        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
+      });
+      wrap.appendChild(metrics);
+      if (d.by_type && Object.keys(d.by_type).length > 1) {
+        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
+        const donut = UI.donutChart(donutData, { size: 100 });
+        if (donut) wrap.appendChild(donut);
+      }
+      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'function_complexity') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
+      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'debug_info') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
+      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
+      wrap.appendChild(metrics);
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    if (name === 'section_sizes') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
+      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
+      wrap.appendChild(metrics);
+      const cats = d.category_breakdown || {};
+      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
+      if (catEntries.length) {
+        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
+        const flame = UI.flameBars(flameItems);
+        if (flame) wrap.appendChild(flame);
+        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
+        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
+        catEntries.forEach(([label, v], i) => {
+          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
+            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
+            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
+      if (sections.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
+        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      return wrap;
+    }
+
+    if (name === 'loop_nesting') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
+      wrap.appendChild(metrics);
+      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
+      if (fns.length) {
+        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
+        const chart = UI.barChart(barData);
+        if (chart) wrap.appendChild(chart);
+      }
+      return wrap;
+    }
+
+    if (name === 'diagnostic_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
+      wrap.appendChild(metrics);
+      const base = d.baseline || {};
+      const prim = d.primary || {};
+      if (base.errors != null || prim.errors != null) {
+        const items = [
+          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
+          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
+          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
+        ];
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
+      if (newDiags.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
+        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'optimization_delta') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
+      wrap.appendChild(metrics);
+      const byType = d.by_type_delta || {};
+      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
+      if (cleanEntries.length) {
+        const items = cleanEntries.map(([label, v]) => ({
+          label: titleCase(label),
+          before: v?.baseline || 0,
+          after: v?.primary || 0,
+        }));
+        const deltaBar = UI.deltaBar(items);
+        if (deltaBar) wrap.appendChild(deltaBar);
+      }
+      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
+      if (passes.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
+        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
+      } else {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'header_depth') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
+      wrap.appendChild(metrics);
+      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
+      if (chains.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
+        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
+      }
+      const most = Array.isArray(d.most_included) ? d.most_included : [];
+      if (most.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
+        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
+      }
+      if (!chains.length && !most.length && !d.max_depth) {
+        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
+      }
+      return wrap;
+    }
+
+    if (name === 'call_frequency') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
+      wrap.appendChild(metrics);
+      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
+      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
+      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
+      if (fanIn.length && fanInHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
+        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      if (fanOut.length && fanOutHasData) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
+        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
+        wrap.appendChild(UI.barChart(barData));
+      }
+      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
+      if (hubs.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
+        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
+      }
+      if (!fanInHasData && !fanOutHasData && fanOut.length) {
+        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
+        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
+      }
+      return wrap;
+    }
+
+    if (name === 'compilation_flow') {
+      const stages = Array.isArray(d.stages) ? d.stages : [];
+      const total = d.total_duration_ms || 0;
+      const slowest = d.slowest_event || {};
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' },
+        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
+      if (slowest.name) {
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Event'),
+          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
+        metrics.appendChild(h('div', { class: 'mini-metric' },
+          h('span', {}, 'Slowest Time'),
+          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
+      }
+      wrap.appendChild(metrics);
+      if (stages.length) {
+        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
+        // Stacked horizontal bar
+        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
+        stages.forEach(s => {
+          const pct = s.pct_of_total || 0;
+          if (pct <= 0) return;
+          const color = colors[s.stage] || '#9B7DB8';
+          const seg = h('div', {
+            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
+                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
+            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
+          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
+          bar.appendChild(seg);
+        });
+        wrap.appendChild(bar);
+        // Legend rows
+        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
+        stages.forEach(s => {
+          const color = colors[s.stage] || '#9B7DB8';
+          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
+            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
+            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
+            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
+            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
+          ));
+        });
+        wrap.appendChild(legend);
+      }
+      return wrap;
+    }
+
+    if (name === 'metric_trends') {
+      const metrics = h('div', { class: 'mini-metrics' });
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
+      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
+      wrap.appendChild(metrics);
+      if (d.functions > 0 && d.instructions > 0) {
+        const donutData = [
+          { label: 'Functions', value: d.functions },
+          { label: 'Globals', value: d.globals || 0 },
+        ].filter(x => x.value > 0);
+        if (donutData.length > 1) {
+          const donut = UI.donutChart(donutData, { size: 90 });
+          if (donut) wrap.appendChild(donut);
+        }
+      }
+      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
+      if (interps.length) {
+        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+        interps.forEach(msg => {
+          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
+        });
+        wrap.appendChild(list);
+      }
+      return wrap;
+    }
+
+    return null;
+  },
+};
+
+/* ============================================================
+   LLVM Advisor — Remarks Explorer View
+   ============================================================ */
+
+const RemarksView = {
+  async render() {
+    const snap = State.get('currentSnapshot');
+    const container = h('div', {});
+    container.appendChild(h('div', { class: 'section-header' }, 'Optimization Remarks Explorer'));
+    Shell.renderMain(container);
+
+    if (!snap) {
+      container.appendChild(h('div', { class: 'empty-state' },
+        h('div', {}, 'Select a snapshot first')));
+      return;
+    }
+
+    const skeleton = h('div', { class: 'dashboard-skeleton', style: { padding: '24px', display: 'flex', flexDirection: 'column', gap: '24px' } },
+      h('div', { style: { height: '80px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' } },
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } }),
+        h('div', { style: { height: '200px', background: 'var(--bg2)', borderRadius: '8px', animation: 'shimmer 1.5s infinite' } })
+      )
+    );
+    container.appendChild(skeleton);
+
+    const [relRes, queryRes] = await Promise.all([
+      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary']),
+    ]);
+
+    if (skeleton.parentNode) skeleton.parentNode.removeChild(skeleton);
+
+    if (!relRes.ok && !queryRes.ok) {
+      container.appendChild(UI.errorCard(
+        'No remarks data available. Capture with llvm.remarks.summary enabled.',
+        () => this.render()
+      ));
+      return;
+    }
+
+    const rel = relRes.ok && relRes.data ? relRes.data : null;
+    const queryUnits = queryRes.ok && Array.isArray(queryRes.data) ? queryRes.data : [];
+
+    // Top-level summary from summary capability
+    const byPass = {}, byType = {};
+    let totalRemarks = 0;
+    queryUnits.forEach(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      results.filter(r => r.capability === 'llvm.remarks.summary').forEach(res => {
+        const v = res.value || {};
+        totalRemarks += Number(v.count || v.remark_count || 0);
+        if (v.by_pass) Object.entries(v.by_pass).forEach(([p, c]) => { byPass[p] = (byPass[p] || 0) + Number(c); });
+        if (v.by_type) Object.entries(v.by_type).forEach(([t, c]) => { byType[t] = (byType[t] || 0) + Number(c); });
+      });
+    });
+
+    // Header stat row
+    const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
+    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
+    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
+    container.appendChild(statRow);
+
+    const grid = h('div', { class: 'overview-grid', style: { marginTop: '0' } });
+
+    // Pass distribution bar chart
+    const passEntries = Object.entries(byPass).sort((a, b) => b[1] - a[1]);
+    if (passEntries.length) {
+      const passData = passEntries.slice(0, 12).map(([label, amount]) => ({ label, amount }));
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks by Pass'),
+        UI.barChart(passData)
+      );
+      grid.appendChild(section);
+    }
+
+    // Remark type donut
+    const typeEntries = Object.entries(byType).filter(([, v]) => v > 0);
+    if (typeEntries.length) {
+      const typeData = typeEntries.map(([label, value]) => ({
+        label: label.charAt(0).toUpperCase() + label.slice(1),
+        value,
+      }));
+      const donut = UI.donutChart(typeData);
+      if (donut) {
+        grid.appendChild(h('div', { class: 'chart-section' },
+          h('h3', {}, 'By Remark Type'),
+          donut
+        ));
+      }
+    }
+
+    // Per-unit remark distribution (long tail)
+    const unitRemarks = queryUnits.map(u => {
+      const results = CapabilityData.normalizeResults(u.results || []);
+      const rem = results.filter(r => r.capability === 'llvm.remarks.summary')
+        .reduce((s, r) => s + Number(r.value?.count || r.value?.remark_count || 0), 0);
+      return { unit_id: u.unit_id, source_path: u.source_path, remarks: rem };
+    }).filter(u => u.remarks > 0).sort((a, b) => b.remarks - a.remarks);
+
+    if (unitRemarks.length) {
+      const flameItems = unitRemarks.slice(0, 10).map(u => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        return { label: file, value: u.remarks };
+      });
+      const section = h('div', { class: 'chart-section' },
+        h('h3', {}, 'Remarks per Unit (top 10)')
+      );
+      const flame = UI.flameBars(flameItems);
+      if (flame) section.appendChild(flame);
+      // Legend with links
+      const legend = h('div', { style: { marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px', fontSize: '11px' } });
+      const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4', '#5B8DB8', '#D4A574'];
+      unitRemarks.slice(0, 10).forEach((u, i) => {
+        const path = u.source_path || u.unit_id || '';
+        const file = path.replace(/\\/g, '/').split('/').pop() || path;
+        legend.appendChild(h('span', {
+          style: { display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer' },
+          onClick: () => Router.navigate(`/units/${encodeURIComponent(u.unit_id)}?snapshot=${encodeURIComponent(snap.id)}`),
+        },
+          h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i], display: 'inline-block', flexShrink: '0' } }),
+          `${file}: ${formatNumber(u.remarks)}`
+        ));
+      });
+      section.appendChild(legend);
+      grid.appendChild(section);
+    }
+
+    container.appendChild(grid);
+
+    // Relational table — top (pass, name) tuples
+    if (rel && rel.columns && rel.strings) {
+      const { columns, strings } = rel;
+      const passes = strings.pass || [];
+      const names = strings.name || [];
+      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+
+      // Count (pass, name) tuples
+      const tuples = {};
+      const passCols = columns.pass || [];
+      const nameCols = columns.name || [];
+      const typeCols = columns.type || [];
+      for (let i = 0; i < passCols.length; i++) {
+        const p = passes[passCols[i]] || '?';
+        const n = names[nameCols[i]] || '?';
+        const key = `${p}\0${n}`;
+        if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
+        const typeName = types[typeCols[i]] || 'unknown';
+        tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
+        tuples[key].count = (tuples[key].count || 0) + 1;
+      }
+
+      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      if (sorted.length) {
+        const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
+          h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
+        );
+        const table = h('table', { class: 'top-units-table' },
+          h('thead', {}, h('tr', {},
+            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+            h('th', { style: { textAlign: 'right' } }, 'Count'),
+            h('th', { style: { textAlign: 'right' } }, 'Missed'),
+            h('th', { style: { textAlign: 'right' } }, 'Passed'),
+          ))
+        );
+        const tbody = h('tbody', {});
+        sorted.forEach(t => {
+          tbody.appendChild(h('tr', {},
+            h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
+            h('td', { style: { fontSize: '11px' } }, t.name),
+            h('td', { class: 'num' }, formatNumber(t.count)),
+            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
+              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
+            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
+              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+          ));
+        });
+        table.appendChild(tbody);
+        tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
+        container.appendChild(tableSection);
+      }
+    }
+  },
+};
+
 /* ============================================================
    LLVM Advisor — Settings View
    ============================================================ */

>From f2a38802a75c47aa38c8da441354f66be73d589e Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 27 May 2026 05:29:25 +0530
Subject: [PATCH 05/41] [llvm-advisor] normalize remark types to canonical
 lowercase keys

All six remark types (unknown, passed, missed, analysis, analysis-fp-commute,
analysis-aliasing, failure) are now uniformly named across the ingestion
pipeline:

- add remarkTypeKey() and allRemarkTypeKeys() in RemarksAnalysisUtils as
  the single source of truth for type -> JSON key mapping; replaces the
  direct use of LLVM's typeToStr() which returns CamelCase strings
  inconsistent with the rest of the JSON API
- RemarksAnalyzer (llvm.remarks.summary): pre-initialize all six keys at
  0 before iterating so the by_type object always has the same shape
  regardless of which types appear in the file
- RemarksDetailAnalyzer (llvm.remarks.detail): use canonical names
- PassImpact insight: update hit-rate lookup keys to lowercase
- OptimizationDelta insight: fix stale comment
- Remarks Explorer (views.js): decode relational type integers using the
  canonical name array; show all six types as table columns, hiding any
  column that is all-zero across the top 20 rows
- unit-detail.js: remove hardcoded type list from empty-state message

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Analysis/IR/RemarksAnalyzer.cpp       |  6 +-
 .../Inspection/RemarksDetailAnalyzer.cpp      |  2 +-
 .../src/Analysis/RemarksAnalysisUtils.cpp     | 21 +++++++
 .../src/Analysis/RemarksAnalysisUtils.h       |  4 ++
 .../src/Client/HTTP/Assets/bundled.html       | 57 ++++++++++++-------
 .../src/Client/HTTP/Assets/index_html.inc     | 57 ++++++++++++-------
 .../src/Client/HTTP/Assets/unit-detail.js     |  2 +-
 .../src/Client/HTTP/Assets/views.js           | 55 ++++++++++++------
 8 files changed, 144 insertions(+), 60 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksAnalyzer.cpp
index 39bee23bbbee3..184886b208c95 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksAnalyzer.cpp
@@ -22,6 +22,8 @@ RemarksAnalyzer::run(const CapabilityContext &Context) {
         int64_t Count = 0;
         json::Object ByPass;
         json::Object ByType;
+        for (StringRef K : allRemarkTypeKeys())
+          ByType[K] = int64_t(0);
         if (Error E = foreachRemark(
                 Path, [&](const remarks::Remark &R) -> Error {
                   ++Count;
@@ -32,8 +34,8 @@ RemarksAnalyzer::run(const CapabilityContext &Context) {
                   json::Value &PassVal = ByPass[PassKey];
                   PassVal = PassVal.getAsInteger().value_or(0) + 1;
 
-                  StringRef Ty = remarks::typeToStr(R.RemarkType);
-                  json::Value &TypeVal = ByType[Ty.str()];
+                  StringRef Ty = remarkTypeKey(R.RemarkType);
+                  json::Value &TypeVal = ByType[Ty];
                   TypeVal = TypeVal.getAsInteger().value_or(0) + 1;
                   return Error::success();
                 }))
diff --git a/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
index b6a4624775699..483dd50c7e756 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
@@ -34,7 +34,7 @@ RemarksDetailAnalyzer::run(const CapabilityContext &Context) {
                   json::Object Item{
                       {"pass", R.PassName.str()},
                       {"name", R.RemarkName.str()},
-                      {"type", remarks::typeToStr(R.RemarkType)},
+                      {"type", remarkTypeKey(R.RemarkType).str()},
                       {"function", R.FunctionName.str()},
                       {"message", R.getArgsAsMsg()},
                   };
diff --git a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
index 30b7a630b679f..85a731c91c161 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
@@ -13,6 +13,27 @@
 using namespace llvm;
 using namespace llvm::advisor;
 
+StringRef llvm::advisor::remarkTypeKey(remarks::Type T) {
+  switch (T) {
+  case remarks::Type::Unknown:          return "unknown";
+  case remarks::Type::Passed:           return "passed";
+  case remarks::Type::Missed:           return "missed";
+  case remarks::Type::Analysis:         return "analysis";
+  case remarks::Type::AnalysisFPCommute: return "analysis-fp-commute";
+  case remarks::Type::AnalysisAliasing: return "analysis-aliasing";
+  case remarks::Type::Failure:          return "failure";
+  }
+  return "unknown";
+}
+
+ArrayRef<StringRef> llvm::advisor::allRemarkTypeKeys() {
+  static constexpr StringRef Keys[] = {
+      "unknown", "passed", "missed", "analysis",
+      "analysis-fp-commute", "analysis-aliasing", "failure",
+  };
+  return Keys;
+}
+
 Error llvm::advisor::foreachRemark(StringRef Path, RemarkVisitor Visitor) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> MB = MemoryBuffer::getFile(Path);
   if (!MB)
diff --git a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.h b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.h
index 2839e2a1ed343..2eebe5ced71f6 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.h
+++ b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.h
@@ -15,6 +15,10 @@ namespace llvm::advisor {
 
 using RemarkVisitor = function_ref<Error(const remarks::Remark &)>;
 
+StringRef remarkTypeKey(remarks::Type T);
+
+ArrayRef<StringRef> allRemarkTypeKeys();
+
 /// Open a YAML remark file and invoke Visitor for each remark.
 Error foreachRemark(StringRef Path, RemarkVisitor Visitor);
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 1e683cb7259e0..79b55bd731e63 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -3254,7 +3254,7 @@
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
       if (!findings.length) {
-        return this.emptyTab('No optimization remarks', 'No missed, passed, or analysis remarks were reported for this unit.');
+        return this.emptyTab('No optimization remarks', 'No optimization remarks were reported for this unit.');
       }
       return h('div', { class: 'capability-stack' },
         UI.passTimeline(findings),
@@ -4532,9 +4532,24 @@
       const { columns, strings } = rel;
       const passes = strings.pass || [];
       const names = strings.name || [];
-      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
-
-      // Count (pass, name) tuples
+      // Canonical type names — must match remarkTypeKey() in RemarksAnalysisUtils.cpp.
+      // Index matches remarks::Type enum: 0=unknown … 6=failure.
+      const REMARK_TYPES = [
+        'unknown', 'passed', 'missed', 'analysis',
+        'analysis-fp-commute', 'analysis-aliasing', 'failure',
+      ];
+      // Subset shown as individual columns in the table (skip unknown/failure
+      // unless they actually appear, to keep the table compact).
+      const TABLE_TYPE_COLS = [
+        { key: 'missed',             label: 'Missed',     color: 'var(--orange)' },
+        { key: 'passed',             label: 'Passed',     color: 'var(--green)'  },
+        { key: 'analysis',           label: 'Analysis',   color: 'var(--teal)'   },
+        { key: 'analysis-fp-commute',label: 'FP-Commute', color: 'var(--fg3)'    },
+        { key: 'analysis-aliasing',  label: 'Aliasing',   color: 'var(--fg3)'    },
+        { key: 'failure',            label: 'Failure',    color: 'var(--red)'    },
+      ];
+
+      // Count (pass, name) tuples, tallying every type.
       const tuples = {};
       const passCols = columns.pass || [];
       const nameCols = columns.name || [];
@@ -4544,34 +4559,38 @@
         const n = names[nameCols[i]] || '?';
         const key = `${p}\0${n}`;
         if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
-        const typeName = types[typeCols[i]] || 'unknown';
+        const typeName = REMARK_TYPES[typeCols[i]] || 'unknown';
         tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
         tuples[key].count = (tuples[key].count || 0) + 1;
       }
 
-      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
-      if (sorted.length) {
+      // Hide columns that are all-zero across the top 20 rows.
+      const top = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      const visibleCols = TABLE_TYPE_COLS.filter(col =>
+        top.some(t => (t.by_type[col.key] || 0) > 0)
+      );
+
+      if (top.length) {
         const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
           h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
         );
-        const table = h('table', { class: 'top-units-table' },
-          h('thead', {}, h('tr', {},
-            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
-            h('th', { style: { textAlign: 'right' } }, 'Count'),
-            h('th', { style: { textAlign: 'right' } }, 'Missed'),
-            h('th', { style: { textAlign: 'right' } }, 'Passed'),
-          ))
+        const thead = h('tr', {},
+          h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+          h('th', { style: { textAlign: 'right' } }, 'Total'),
+          ...visibleCols.map(col => h('th', { style: { textAlign: 'right' } }, col.label))
         );
+        const table = h('table', { class: 'top-units-table' }, h('thead', {}, thead));
         const tbody = h('tbody', {});
-        sorted.forEach(t => {
+        top.forEach(t => {
           tbody.appendChild(h('tr', {},
             h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
             h('td', { style: { fontSize: '11px' } }, t.name),
             h('td', { class: 'num' }, formatNumber(t.count)),
-            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
-              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
-            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
-              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+            ...visibleCols.map(col => {
+              const v = t.by_type[col.key] || 0;
+              return h('td', { class: 'num', style: { color: v > 0 ? col.color : 'var(--fg3)' } },
+                v > 0 ? formatNumber(v) : '–');
+            })
           ));
         });
         table.appendChild(tbody);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 69d57f31b979a..cce1d5eb918cd 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -3257,7 +3257,7 @@ const UnitDetailView = {
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
       if (!findings.length) {
-        return this.emptyTab('No optimization remarks', 'No missed, passed, or analysis remarks were reported for this unit.');
+        return this.emptyTab('No optimization remarks', 'No optimization remarks were reported for this unit.');
       }
       return h('div', { class: 'capability-stack' },
         UI.passTimeline(findings),
@@ -4535,9 +4535,24 @@ const RemarksView = {
       const { columns, strings } = rel;
       const passes = strings.pass || [];
       const names = strings.name || [];
-      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
-
-      // Count (pass, name) tuples
+      // Canonical type names — must match remarkTypeKey() in RemarksAnalysisUtils.cpp.
+      // Index matches remarks::Type enum: 0=unknown … 6=failure.
+      const REMARK_TYPES = [
+        'unknown', 'passed', 'missed', 'analysis',
+        'analysis-fp-commute', 'analysis-aliasing', 'failure',
+      ];
+      // Subset shown as individual columns in the table (skip unknown/failure
+      // unless they actually appear, to keep the table compact).
+      const TABLE_TYPE_COLS = [
+        { key: 'missed',             label: 'Missed',     color: 'var(--orange)' },
+        { key: 'passed',             label: 'Passed',     color: 'var(--green)'  },
+        { key: 'analysis',           label: 'Analysis',   color: 'var(--teal)'   },
+        { key: 'analysis-fp-commute',label: 'FP-Commute', color: 'var(--fg3)'    },
+        { key: 'analysis-aliasing',  label: 'Aliasing',   color: 'var(--fg3)'    },
+        { key: 'failure',            label: 'Failure',    color: 'var(--red)'    },
+      ];
+
+      // Count (pass, name) tuples, tallying every type.
       const tuples = {};
       const passCols = columns.pass || [];
       const nameCols = columns.name || [];
@@ -4547,34 +4562,38 @@ const RemarksView = {
         const n = names[nameCols[i]] || '?';
         const key = `${p}\0${n}`;
         if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
-        const typeName = types[typeCols[i]] || 'unknown';
+        const typeName = REMARK_TYPES[typeCols[i]] || 'unknown';
         tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
         tuples[key].count = (tuples[key].count || 0) + 1;
       }
 
-      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
-      if (sorted.length) {
+      // Hide columns that are all-zero across the top 20 rows.
+      const top = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      const visibleCols = TABLE_TYPE_COLS.filter(col =>
+        top.some(t => (t.by_type[col.key] || 0) > 0)
+      );
+
+      if (top.length) {
         const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
           h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
         );
-        const table = h('table', { class: 'top-units-table' },
-          h('thead', {}, h('tr', {},
-            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
-            h('th', { style: { textAlign: 'right' } }, 'Count'),
-            h('th', { style: { textAlign: 'right' } }, 'Missed'),
-            h('th', { style: { textAlign: 'right' } }, 'Passed'),
-          ))
+        const thead = h('tr', {},
+          h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+          h('th', { style: { textAlign: 'right' } }, 'Total'),
+          ...visibleCols.map(col => h('th', { style: { textAlign: 'right' } }, col.label))
         );
+        const table = h('table', { class: 'top-units-table' }, h('thead', {}, thead));
         const tbody = h('tbody', {});
-        sorted.forEach(t => {
+        top.forEach(t => {
           tbody.appendChild(h('tr', {},
             h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
             h('td', { style: { fontSize: '11px' } }, t.name),
             h('td', { class: 'num' }, formatNumber(t.count)),
-            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
-              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
-            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
-              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+            ...visibleCols.map(col => {
+              const v = t.by_type[col.key] || 0;
+              return h('td', { class: 'num', style: { color: v > 0 ? col.color : 'var(--fg3)' } },
+                v > 0 ? formatNumber(v) : '–');
+            })
           ));
         });
         table.appendChild(tbody);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
index d70eadb4f123b..6501efd72e938 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
@@ -201,7 +201,7 @@ const UnitDetailView = {
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
       if (!findings.length) {
-        return this.emptyTab('No optimization remarks', 'No missed, passed, or analysis remarks were reported for this unit.');
+        return this.emptyTab('No optimization remarks', 'No optimization remarks were reported for this unit.');
       }
       return h('div', { class: 'capability-stack' },
         UI.passTimeline(findings),
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index b98bbed150b3f..727c8ba8a2f9d 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -841,9 +841,24 @@ const RemarksView = {
       const { columns, strings } = rel;
       const passes = strings.pass || [];
       const names = strings.name || [];
-      const types = [null, 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
-
-      // Count (pass, name) tuples
+      // Canonical type names — must match remarkTypeKey() in RemarksAnalysisUtils.cpp.
+      // Index matches remarks::Type enum: 0=unknown … 6=failure.
+      const REMARK_TYPES = [
+        'unknown', 'passed', 'missed', 'analysis',
+        'analysis-fp-commute', 'analysis-aliasing', 'failure',
+      ];
+      // Subset shown as individual columns in the table (skip unknown/failure
+      // unless they actually appear, to keep the table compact).
+      const TABLE_TYPE_COLS = [
+        { key: 'missed',             label: 'Missed',     color: 'var(--orange)' },
+        { key: 'passed',             label: 'Passed',     color: 'var(--green)'  },
+        { key: 'analysis',           label: 'Analysis',   color: 'var(--teal)'   },
+        { key: 'analysis-fp-commute',label: 'FP-Commute', color: 'var(--fg3)'    },
+        { key: 'analysis-aliasing',  label: 'Aliasing',   color: 'var(--fg3)'    },
+        { key: 'failure',            label: 'Failure',    color: 'var(--red)'    },
+      ];
+
+      // Count (pass, name) tuples, tallying every type.
       const tuples = {};
       const passCols = columns.pass || [];
       const nameCols = columns.name || [];
@@ -853,34 +868,38 @@ const RemarksView = {
         const n = names[nameCols[i]] || '?';
         const key = `${p}\0${n}`;
         if (!tuples[key]) tuples[key] = { pass: p, name: n, by_type: {} };
-        const typeName = types[typeCols[i]] || 'unknown';
+        const typeName = REMARK_TYPES[typeCols[i]] || 'unknown';
         tuples[key].by_type[typeName] = (tuples[key].by_type[typeName] || 0) + 1;
         tuples[key].count = (tuples[key].count || 0) + 1;
       }
 
-      const sorted = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
-      if (sorted.length) {
+      // Hide columns that are all-zero across the top 20 rows.
+      const top = Object.values(tuples).sort((a, b) => b.count - a.count).slice(0, 20);
+      const visibleCols = TABLE_TYPE_COLS.filter(col =>
+        top.some(t => (t.by_type[col.key] || 0) > 0)
+      );
+
+      if (top.length) {
         const tableSection = h('div', { class: 'chart-section', style: { marginTop: '18px' } },
           h('h3', {}, `Top (Pass, Remark) Pairs — ${rel.count} total remarks`)
         );
-        const table = h('table', { class: 'top-units-table' },
-          h('thead', {}, h('tr', {},
-            h('th', {}, 'Pass'), h('th', {}, 'Remark'),
-            h('th', { style: { textAlign: 'right' } }, 'Count'),
-            h('th', { style: { textAlign: 'right' } }, 'Missed'),
-            h('th', { style: { textAlign: 'right' } }, 'Passed'),
-          ))
+        const thead = h('tr', {},
+          h('th', {}, 'Pass'), h('th', {}, 'Remark'),
+          h('th', { style: { textAlign: 'right' } }, 'Total'),
+          ...visibleCols.map(col => h('th', { style: { textAlign: 'right' } }, col.label))
         );
+        const table = h('table', { class: 'top-units-table' }, h('thead', {}, thead));
         const tbody = h('tbody', {});
-        sorted.forEach(t => {
+        top.forEach(t => {
           tbody.appendChild(h('tr', {},
             h('td', { class: 'mono', style: { fontSize: '11px' } }, t.pass),
             h('td', { style: { fontSize: '11px' } }, t.name),
             h('td', { class: 'num' }, formatNumber(t.count)),
-            h('td', { class: 'num', style: { color: (t.by_type.missed || 0) > 0 ? 'var(--orange)' : 'var(--fg3)' } },
-              t.by_type.missed ? formatNumber(t.by_type.missed) : '–'),
-            h('td', { class: 'num', style: { color: (t.by_type.passed || 0) > 0 ? 'var(--green)' : 'var(--fg3)' } },
-              t.by_type.passed ? formatNumber(t.by_type.passed) : '–'),
+            ...visibleCols.map(col => {
+              const v = t.by_type[col.key] || 0;
+              return h('td', { class: 'num', style: { color: v > 0 ? col.color : 'var(--fg3)' } },
+                v > 0 ? formatNumber(v) : '–');
+            })
           ));
         });
         table.appendChild(tbody);

>From 5d6ceb56de627dc94b08d766389044da0db1a8cd Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 27 May 2026 06:22:23 +0530
Subject: [PATCH 06/41] [llvm-advisor] bump remarks capability versions to
 invalidate stale cache

llvm.remarks.summary and llvm.remarks.detail changed their output format
in the previous commit (lowercase type keys, all six pre-initialized).
Bump both to version 2 so the run-key hash changes and old cached results
with capitalized keys are not returned.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 llvm/tools/llvm-advisor/config/capabilities/catalog.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-advisor/config/capabilities/catalog.json b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
index 68e919fbd8da9..cb80a552fc0c0 100644
--- a/llvm/tools/llvm-advisor/config/capabilities/catalog.json
+++ b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
@@ -3,7 +3,7 @@
     {
       "id": "llvm.remarks.summary",
       "name": "Optimization remarks summary",
-      "version": "1",
+      "version": "2",
       "runner": "builtin.remarks_summary",
       "summary": "remarks summary requires an optimization remarks artifact",
       "readiness": "L1",
@@ -45,7 +45,7 @@
     {
       "id": "llvm.remarks.detail",
       "name": "Optimization remarks detail",
-      "version": "1",
+      "version": "2",
       "runner": "builtin.remarks_detail",
       "summary": "remarks detail requires an optimization remarks artifact",
       "readiness": "L1",

>From 770b48d054a1b6fdc760ce8f2b6c3b038e29f5a0 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Thu, 28 May 2026 03:20:13 +0530
Subject: [PATCH 07/41] [llvm-advisor] add virtualised triage grid to remarks
 view

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 399 ++++++++++++++++++
 .../src/Client/HTTP/Assets/index_html.inc     | 399 ++++++++++++++++++
 .../src/Client/HTTP/Assets/styles.css         |  51 +++
 .../src/Client/HTTP/Assets/views.js           | 348 +++++++++++++++
 4 files changed, 1197 insertions(+)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 79b55bd731e63..e25cab904c6c4 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -674,6 +674,57 @@
   .impact-grid{grid-template-columns:1fr}
 }
 
+/* Triage Grid — virtualised, filterable per-remark table.
+   Lives inside a .chart-section so the outer card chrome is inherited. */
+.triage-grid{padding:16px 18px}
+.triage-header-row{display:flex;align-items:center;gap:12px;margin-bottom:10px}
+.triage-header-row h3{margin:0;font-size:13px}
+.triage-counter{font-family:var(--mono);font-size:11px;color:var(--fg2)}
+.triage-reset{margin-left:auto;background:transparent;border:1px solid var(--border);border-radius:var(--r);padding:4px 10px;font-size:11px;color:var(--fg2);cursor:pointer}
+.triage-reset:hover{border-color:var(--accent);color:var(--accent)}
+
+.triage-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--r);margin-bottom:8px}
+.triage-input{flex:1;min-width:120px;padding:5px 8px;font-size:11px;font-family:var(--mono);background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)}
+.triage-input:focus{outline:none;border-color:var(--accent)}
+.triage-input::placeholder{color:var(--fg3)}
+
+.triage-chips{display:flex;gap:4px;flex-wrap:wrap}
+.triage-chip{font-size:10px;font-family:var(--mono);padding:4px 8px;border-radius:99px;border:1px solid var(--border);background:var(--bg);color:var(--fg2);cursor:pointer;transition:background var(--fast),color var(--fast),border-color var(--fast)}
+.triage-chip:hover{border-color:var(--accent);color:var(--fg)}
+.triage-chip.on{background:var(--accent);color:#fff;border-color:var(--accent)}
+
+.triage-thead{display:flex;align-items:center;border:1px solid var(--border);border-bottom:0;background:var(--bg2);font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);user-select:none;min-width:max-content;border-radius:var(--r) var(--r) 0 0}
+.triage-th{padding:8px 10px;flex-shrink:0;display:flex;align-items:center;gap:4px}
+.triage-th.right{justify-content:flex-end}
+.triage-th.sortable{cursor:pointer}
+.triage-th.sortable:hover{color:var(--fg)}
+.triage-th.sorted{color:var(--accent)}
+.triage-sort-indicator{font-size:8px;line-height:1}
+
+/* Virtualised body: a fixed-height viewport scrolling over a tall spacer
+   that holds the row pool absolutely-positioned at row * rowHeight. */
+.triage-viewport{position:relative;overflow-y:auto;overflow-x:auto;border:1px solid var(--border);border-radius:0 0 var(--r) var(--r);background:var(--bg)}
+.triage-spacer{position:relative;min-width:max-content}
+.triage-row{position:absolute;left:0;display:flex;align-items:center;border-bottom:1px solid var(--bg2);will-change:top;min-width:max-content}
+.triage-row:hover{background:var(--bg2)}
+.triage-td{padding:0 10px;flex-shrink:0;font-size:11px;line-height:1;color:var(--fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:inline-block}
+.triage-td.mono{font-family:var(--mono)}
+.triage-td.right{text-align:right}
+.triage-td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
+.triage-td-missing{color:var(--fg3)}
+
+/* Type pills — color-coded by remarks::Type. */
+.triage-type{font-family:var(--mono);font-size:10px;padding:2px 6px;border-radius:4px}
+.triage-type-passed{color:var(--green);background:rgba(90,200,138,.08)}
+.triage-type-missed{color:var(--orange);background:rgba(255,179,71,.10)}
+.triage-type-analysis{color:var(--teal);background:rgba(123,224,214,.10)}
+.triage-type-analysis-fp-commute{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-analysis-aliasing{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-failure{color:var(--red);background:rgba(255,107,110,.10)}
+.triage-type-unknown{color:var(--fg3);background:var(--bg2)}
+
+.triage-empty{position:absolute;inset:0;display:none;align-items:center;justify-content:center;color:var(--fg3);font-size:12px;pointer-events:none}
+
   </style>
 </head>
 <body>
@@ -4597,7 +4648,355 @@
         tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
         container.appendChild(tableSection);
       }
+
+      // Full triage grid: virtualised, filterable, sortable view of every
+      // remark in the relational payload. Lives below the summary tables.
+      container.appendChild(this._renderTriageGrid(rel));
+    }
+  },
+
+  // Triage Grid — Phase 1B of the proposal, against the C++ relational
+  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
+  // of ~32 row elements floats over an absolute-positioned spacer so that
+  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
+  // integer columns first; strings are dereferenced only for display.
+  _renderTriageGrid(rel) {
+    const { columns, strings } = rel;
+    const total = rel.count || 0;
+
+    // Canonical lowercase type keys; index = remarks::Type enum value.
+    const TYPE_NAMES = [
+      'unknown', 'passed', 'missed', 'analysis',
+      'analysis-fp-commute', 'analysis-aliasing', 'failure',
+    ];
+    const TYPE_LABELS = {
+      'unknown': 'Unknown',
+      'passed': 'Passed',
+      'missed': 'Missed',
+      'analysis': 'Analysis',
+      'analysis-fp-commute': 'FP-Commute',
+      'analysis-aliasing': 'Aliasing',
+      'failure': 'Failure',
+    };
+
+    // Column descriptors. `key` maps to a getter that resolves the integer
+    // column to a displayable value (string for text cells, number for
+    // numeric cells, null for missing).
+    const COLS = [
+      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
+        idx: (i) => columns.unit ? columns.unit[i] : -1 },
+      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => strings.pass[columns.pass[i]] || '?',
+        idx: (i) => columns.pass[i] },
+      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => strings.name[columns.name[i]] || '?',
+        idx: (i) => columns.name[i] },
+      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
+        idx: (i) => columns.type[i] },
+      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
+        idx: (i) => columns.function[i] },
+      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
+        get: (i) => {
+          const fi = columns.file[i];
+          if (fi < 0) return null;
+          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
+          return `${file}:${columns.line[i]}:${columns.column[i]}`;
+        } },
+      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
+        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
+        idx: (i) => columns.hotness[i] },
+    ];
+
+    // Mutable state -------------------------------------------------------
+    let filtered = new Int32Array(total);
+    for (let i = 0; i < total; i++) filtered[i] = i;
+    let filteredLen = total;
+    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
+    let sortColId = null;
+    let sortDir = 1; // 1 = ascending, -1 = descending
+
+    // DOM -----------------------------------------------------------------
+    const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
+
+    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
+    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    wrap.appendChild(h('div', { class: 'triage-header-row' },
+      h('h3', { style: { margin: '0' } }, 'All Remarks'),
+      counter,
+      resetBtn,
+    ));
+
+    // Filter bar. Text inputs filter on a case-insensitive substring of the
+    // matching string column; type chips toggle a set of allowed type enum
+    // values; hotness slider filters on minimum hotness.
+    const filterBar = h('div', { class: 'triage-filter-bar' });
+    const textFields = [
+      { key: 'pass',   placeholder: 'pass…' },
+      { key: 'name',   placeholder: 'remark name…' },
+      { key: 'func',   placeholder: 'function…' },
+      { key: 'source', placeholder: 'source file…' },
+    ];
+    textFields.forEach(f => {
+      const inp = h('input', {
+        class: 'triage-input',
+        type: 'search',
+        placeholder: f.placeholder,
+        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
+      });
+      filterBar.appendChild(inp);
+    });
+
+    // Type chips — clickable on/off filters for each remarks::Type value.
+    const typeChipBox = h('div', { class: 'triage-chips' });
+    TYPE_NAMES.forEach((name, enumVal) => {
+      if (name === 'unknown') return; // hide unless they actually appear
+      const chip = h('button', {
+        class: `triage-chip triage-chip-${name}`,
+        title: `Toggle ${TYPE_LABELS[name]}`,
+        onClick: () => {
+          if (filters.types.has(enumVal)) {
+            filters.types.delete(enumVal);
+            chip.classList.remove('on');
+          } else {
+            filters.types.add(enumVal);
+            chip.classList.add('on');
+          }
+          refilter();
+        },
+      }, TYPE_LABELS[name]);
+      typeChipBox.appendChild(chip);
+    });
+    filterBar.appendChild(typeChipBox);
+    wrap.appendChild(filterBar);
+
+    // Header row (sortable columns).
+    const tHead = h('div', { class: 'triage-thead' });
+    const thEls = {};
+    COLS.forEach(col => {
+      const th = h('div', {
+        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
+        style: { width: col.width + 'px' },
+        onClick: col.sortable ? () => onSort(col.id) : null,
+      },
+        h('span', { class: 'triage-th-label' }, col.label),
+        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
+      );
+      thEls[col.id] = th;
+      tHead.appendChild(th);
+    });
+    wrap.appendChild(tHead);
+
+    // Virtualised viewport.
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
+
+    const viewport = h('div', {
+      class: 'triage-viewport',
+      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
+    });
+    const spacer = h('div', { class: 'triage-spacer' });
+    spacer.style.height = `${total * ROW_H}px`;
+    viewport.appendChild(spacer);
+
+    // Pre-allocate the row pool once. Each row is an absolutely-positioned
+    // flex container with one span per column. Scroll only mutates each
+    // span's textContent and the row's top position.
+    const pool = [];
+    for (let p = 0; p < POOL_SIZE; p++) {
+      const row = h('div', { class: 'triage-row' });
+      row.style.height = `${ROW_H}px`;
+      const cells = COLS.map(col => h('span', {
+        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
+        style: { width: col.width + 'px' },
+      }, ''));
+      cells.forEach(c => row.appendChild(c));
+      spacer.appendChild(row);
+      pool.push({ row, cells });
     }
+    wrap.appendChild(viewport);
+
+    // Empty-state element shown when filteredLen === 0.
+    const emptyEl = h('div', { class: 'triage-empty' },
+      'No remarks match the current filters.'
+    );
+    viewport.appendChild(emptyEl);
+
+    // -----------------------------------------------------------------------
+    // Render the visible window. Called on scroll, filter, sort.
+    // -----------------------------------------------------------------------
+    const renderVisible = () => {
+      const len = filteredLen;
+      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const scrollTop = viewport.scrollTop;
+      const first = Math.max(0, Math.floor(scrollTop / ROW_H));
+      for (let p = 0; p < pool.length; p++) {
+        const visibleIdx = first + p;
+        const { row, cells } = pool[p];
+        if (visibleIdx >= len) {
+          row.style.display = 'none';
+          continue;
+        }
+        const r = filtered[visibleIdx];
+        row.style.display = '';
+        row.style.top = `${visibleIdx * ROW_H}px`;
+        for (let c = 0; c < COLS.length; c++) {
+          const col = COLS[c];
+          const cell = cells[c];
+          const val = col.get(r);
+          if (val === null || val === undefined) {
+            cell.textContent = '–';
+            cell.classList.add('triage-td-missing');
+          } else {
+            cell.classList.remove('triage-td-missing');
+            if (col.id === 'unit') {
+              cell.textContent = String(val).slice(0, 10);
+              cell.title = val;
+            } else if (col.id === 'type') {
+              cell.textContent = TYPE_LABELS[val] || val;
+              cell.className = `triage-td triage-type triage-type-${val}`;
+            } else if (col.num) {
+              cell.textContent = formatNumber(val);
+            } else {
+              cell.textContent = val;
+              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
+                cell.title = val;
+              }
+            }
+          }
+        }
+      }
+    };
+
+    // -----------------------------------------------------------------------
+    // Rebuild the filtered index array. O(N), runs on every filter change.
+    // -----------------------------------------------------------------------
+    const refilter = () => {
+      const out = new Int32Array(total);
+      let n = 0;
+      const fPass = filters.pass;
+      const fName = filters.name;
+      const fFunc = filters.func;
+      const fSource = filters.source;
+      const fTypes = filters.types;
+      const useTypes = fTypes.size > 0;
+
+      for (let i = 0; i < total; i++) {
+        if (useTypes && !fTypes.has(columns.type[i])) continue;
+        if (fPass) {
+          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
+          if (!s.includes(fPass)) continue;
+        }
+        if (fName) {
+          const s = (strings.name[columns.name[i]] || '').toLowerCase();
+          if (!s.includes(fName)) continue;
+        }
+        if (fFunc) {
+          const fi = columns.function[i];
+          if (fi < 0) continue;
+          const s = (strings.function[fi] || '').toLowerCase();
+          if (!s.includes(fFunc)) continue;
+        }
+        if (fSource) {
+          const fi = columns.file[i];
+          if (fi < 0) continue;
+          const s = (strings.file[fi] || '').toLowerCase();
+          if (!s.includes(fSource)) continue;
+        }
+        out[n++] = i;
+      }
+      filtered = out;
+      filteredLen = n;
+      spacer.style.height = `${n * ROW_H}px`;
+      viewport.scrollTop = 0;
+      counter.textContent = n === total
+        ? `${formatNumber(total)} remarks`
+        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
+      if (sortColId) applySort();
+      renderVisible();
+    };
+
+    // -----------------------------------------------------------------------
+    // Sort the filtered index array in place, then re-render.
+    // -----------------------------------------------------------------------
+    const applySort = () => {
+      const col = COLS.find(c => c.id === sortColId);
+      if (!col) return;
+      const dir = sortDir;
+      const view = Array.from(filtered.subarray(0, filteredLen));
+      if (col.idx) {
+        // Numeric / index sort, fast path. -1 sentinels sort last regardless
+        // of direction so missing values don't crowd the top.
+        view.sort((a, b) => {
+          const va = col.idx(a);
+          const vb = col.idx(b);
+          if (va < 0 && vb < 0) return 0;
+          if (va < 0) return 1;
+          if (vb < 0) return -1;
+          return (va - vb) * dir;
+        });
+      } else {
+        // Lexicographic fallback for text-only columns without an .idx.
+        view.sort((a, b) => {
+          const va = (col.get(a) || '').toString();
+          const vb = (col.get(b) || '').toString();
+          return va.localeCompare(vb) * dir;
+        });
+      }
+      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
+    };
+
+    const onSort = (colId) => {
+      if (sortColId === colId) {
+        sortDir = -sortDir;
+      } else {
+        sortColId = colId;
+        sortDir = 1;
+      }
+      applySort();
+      // Update sort indicators in the header.
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (!ind) return;
+        if (c.id === sortColId) {
+          ind.textContent = sortDir === 1 ? '▲' : '▼';
+          th.classList.add('sorted');
+        } else {
+          ind.textContent = '';
+          th.classList.remove('sorted');
+        }
+      });
+      viewport.scrollTop = 0;
+      renderVisible();
+    };
+
+    const resetAll = () => {
+      filters.pass = filters.name = filters.func = filters.source = '';
+      filters.types.clear();
+      // Reset DOM
+      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
+      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
+      sortColId = null;
+      sortDir = 1;
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        th.classList.remove('sorted');
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (ind) ind.textContent = '';
+      });
+      refilter();
+    };
+
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
+
+    // Initial render — defer until the viewport is laid out in the document.
+    requestAnimationFrame(renderVisible);
+
+    return wrap;
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index cce1d5eb918cd..516ef6614520b 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -677,6 +677,57 @@ html.dark{
   .impact-grid{grid-template-columns:1fr}
 }
 
+/* Triage Grid — virtualised, filterable per-remark table.
+   Lives inside a .chart-section so the outer card chrome is inherited. */
+.triage-grid{padding:16px 18px}
+.triage-header-row{display:flex;align-items:center;gap:12px;margin-bottom:10px}
+.triage-header-row h3{margin:0;font-size:13px}
+.triage-counter{font-family:var(--mono);font-size:11px;color:var(--fg2)}
+.triage-reset{margin-left:auto;background:transparent;border:1px solid var(--border);border-radius:var(--r);padding:4px 10px;font-size:11px;color:var(--fg2);cursor:pointer}
+.triage-reset:hover{border-color:var(--accent);color:var(--accent)}
+
+.triage-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--r);margin-bottom:8px}
+.triage-input{flex:1;min-width:120px;padding:5px 8px;font-size:11px;font-family:var(--mono);background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)}
+.triage-input:focus{outline:none;border-color:var(--accent)}
+.triage-input::placeholder{color:var(--fg3)}
+
+.triage-chips{display:flex;gap:4px;flex-wrap:wrap}
+.triage-chip{font-size:10px;font-family:var(--mono);padding:4px 8px;border-radius:99px;border:1px solid var(--border);background:var(--bg);color:var(--fg2);cursor:pointer;transition:background var(--fast),color var(--fast),border-color var(--fast)}
+.triage-chip:hover{border-color:var(--accent);color:var(--fg)}
+.triage-chip.on{background:var(--accent);color:#fff;border-color:var(--accent)}
+
+.triage-thead{display:flex;align-items:center;border:1px solid var(--border);border-bottom:0;background:var(--bg2);font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);user-select:none;min-width:max-content;border-radius:var(--r) var(--r) 0 0}
+.triage-th{padding:8px 10px;flex-shrink:0;display:flex;align-items:center;gap:4px}
+.triage-th.right{justify-content:flex-end}
+.triage-th.sortable{cursor:pointer}
+.triage-th.sortable:hover{color:var(--fg)}
+.triage-th.sorted{color:var(--accent)}
+.triage-sort-indicator{font-size:8px;line-height:1}
+
+/* Virtualised body: a fixed-height viewport scrolling over a tall spacer
+   that holds the row pool absolutely-positioned at row * rowHeight. */
+.triage-viewport{position:relative;overflow-y:auto;overflow-x:auto;border:1px solid var(--border);border-radius:0 0 var(--r) var(--r);background:var(--bg)}
+.triage-spacer{position:relative;min-width:max-content}
+.triage-row{position:absolute;left:0;display:flex;align-items:center;border-bottom:1px solid var(--bg2);will-change:top;min-width:max-content}
+.triage-row:hover{background:var(--bg2)}
+.triage-td{padding:0 10px;flex-shrink:0;font-size:11px;line-height:1;color:var(--fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:inline-block}
+.triage-td.mono{font-family:var(--mono)}
+.triage-td.right{text-align:right}
+.triage-td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
+.triage-td-missing{color:var(--fg3)}
+
+/* Type pills — color-coded by remarks::Type. */
+.triage-type{font-family:var(--mono);font-size:10px;padding:2px 6px;border-radius:4px}
+.triage-type-passed{color:var(--green);background:rgba(90,200,138,.08)}
+.triage-type-missed{color:var(--orange);background:rgba(255,179,71,.10)}
+.triage-type-analysis{color:var(--teal);background:rgba(123,224,214,.10)}
+.triage-type-analysis-fp-commute{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-analysis-aliasing{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-failure{color:var(--red);background:rgba(255,107,110,.10)}
+.triage-type-unknown{color:var(--fg3);background:var(--bg2)}
+
+.triage-empty{position:absolute;inset:0;display:none;align-items:center;justify-content:center;color:var(--fg3);font-size:12px;pointer-events:none}
+
   </style>
 </head>
 <body>
@@ -4600,7 +4651,355 @@ const RemarksView = {
         tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
         container.appendChild(tableSection);
       }
+
+      // Full triage grid: virtualised, filterable, sortable view of every
+      // remark in the relational payload. Lives below the summary tables.
+      container.appendChild(this._renderTriageGrid(rel));
+    }
+  },
+
+  // Triage Grid — Phase 1B of the proposal, against the C++ relational
+  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
+  // of ~32 row elements floats over an absolute-positioned spacer so that
+  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
+  // integer columns first; strings are dereferenced only for display.
+  _renderTriageGrid(rel) {
+    const { columns, strings } = rel;
+    const total = rel.count || 0;
+
+    // Canonical lowercase type keys; index = remarks::Type enum value.
+    const TYPE_NAMES = [
+      'unknown', 'passed', 'missed', 'analysis',
+      'analysis-fp-commute', 'analysis-aliasing', 'failure',
+    ];
+    const TYPE_LABELS = {
+      'unknown': 'Unknown',
+      'passed': 'Passed',
+      'missed': 'Missed',
+      'analysis': 'Analysis',
+      'analysis-fp-commute': 'FP-Commute',
+      'analysis-aliasing': 'Aliasing',
+      'failure': 'Failure',
+    };
+
+    // Column descriptors. `key` maps to a getter that resolves the integer
+    // column to a displayable value (string for text cells, number for
+    // numeric cells, null for missing).
+    const COLS = [
+      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
+        idx: (i) => columns.unit ? columns.unit[i] : -1 },
+      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => strings.pass[columns.pass[i]] || '?',
+        idx: (i) => columns.pass[i] },
+      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => strings.name[columns.name[i]] || '?',
+        idx: (i) => columns.name[i] },
+      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
+        idx: (i) => columns.type[i] },
+      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
+        idx: (i) => columns.function[i] },
+      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
+        get: (i) => {
+          const fi = columns.file[i];
+          if (fi < 0) return null;
+          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
+          return `${file}:${columns.line[i]}:${columns.column[i]}`;
+        } },
+      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
+        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
+        idx: (i) => columns.hotness[i] },
+    ];
+
+    // Mutable state -------------------------------------------------------
+    let filtered = new Int32Array(total);
+    for (let i = 0; i < total; i++) filtered[i] = i;
+    let filteredLen = total;
+    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
+    let sortColId = null;
+    let sortDir = 1; // 1 = ascending, -1 = descending
+
+    // DOM -----------------------------------------------------------------
+    const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
+
+    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
+    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    wrap.appendChild(h('div', { class: 'triage-header-row' },
+      h('h3', { style: { margin: '0' } }, 'All Remarks'),
+      counter,
+      resetBtn,
+    ));
+
+    // Filter bar. Text inputs filter on a case-insensitive substring of the
+    // matching string column; type chips toggle a set of allowed type enum
+    // values; hotness slider filters on minimum hotness.
+    const filterBar = h('div', { class: 'triage-filter-bar' });
+    const textFields = [
+      { key: 'pass',   placeholder: 'pass…' },
+      { key: 'name',   placeholder: 'remark name…' },
+      { key: 'func',   placeholder: 'function…' },
+      { key: 'source', placeholder: 'source file…' },
+    ];
+    textFields.forEach(f => {
+      const inp = h('input', {
+        class: 'triage-input',
+        type: 'search',
+        placeholder: f.placeholder,
+        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
+      });
+      filterBar.appendChild(inp);
+    });
+
+    // Type chips — clickable on/off filters for each remarks::Type value.
+    const typeChipBox = h('div', { class: 'triage-chips' });
+    TYPE_NAMES.forEach((name, enumVal) => {
+      if (name === 'unknown') return; // hide unless they actually appear
+      const chip = h('button', {
+        class: `triage-chip triage-chip-${name}`,
+        title: `Toggle ${TYPE_LABELS[name]}`,
+        onClick: () => {
+          if (filters.types.has(enumVal)) {
+            filters.types.delete(enumVal);
+            chip.classList.remove('on');
+          } else {
+            filters.types.add(enumVal);
+            chip.classList.add('on');
+          }
+          refilter();
+        },
+      }, TYPE_LABELS[name]);
+      typeChipBox.appendChild(chip);
+    });
+    filterBar.appendChild(typeChipBox);
+    wrap.appendChild(filterBar);
+
+    // Header row (sortable columns).
+    const tHead = h('div', { class: 'triage-thead' });
+    const thEls = {};
+    COLS.forEach(col => {
+      const th = h('div', {
+        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
+        style: { width: col.width + 'px' },
+        onClick: col.sortable ? () => onSort(col.id) : null,
+      },
+        h('span', { class: 'triage-th-label' }, col.label),
+        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
+      );
+      thEls[col.id] = th;
+      tHead.appendChild(th);
+    });
+    wrap.appendChild(tHead);
+
+    // Virtualised viewport.
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
+
+    const viewport = h('div', {
+      class: 'triage-viewport',
+      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
+    });
+    const spacer = h('div', { class: 'triage-spacer' });
+    spacer.style.height = `${total * ROW_H}px`;
+    viewport.appendChild(spacer);
+
+    // Pre-allocate the row pool once. Each row is an absolutely-positioned
+    // flex container with one span per column. Scroll only mutates each
+    // span's textContent and the row's top position.
+    const pool = [];
+    for (let p = 0; p < POOL_SIZE; p++) {
+      const row = h('div', { class: 'triage-row' });
+      row.style.height = `${ROW_H}px`;
+      const cells = COLS.map(col => h('span', {
+        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
+        style: { width: col.width + 'px' },
+      }, ''));
+      cells.forEach(c => row.appendChild(c));
+      spacer.appendChild(row);
+      pool.push({ row, cells });
     }
+    wrap.appendChild(viewport);
+
+    // Empty-state element shown when filteredLen === 0.
+    const emptyEl = h('div', { class: 'triage-empty' },
+      'No remarks match the current filters.'
+    );
+    viewport.appendChild(emptyEl);
+
+    // -----------------------------------------------------------------------
+    // Render the visible window. Called on scroll, filter, sort.
+    // -----------------------------------------------------------------------
+    const renderVisible = () => {
+      const len = filteredLen;
+      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const scrollTop = viewport.scrollTop;
+      const first = Math.max(0, Math.floor(scrollTop / ROW_H));
+      for (let p = 0; p < pool.length; p++) {
+        const visibleIdx = first + p;
+        const { row, cells } = pool[p];
+        if (visibleIdx >= len) {
+          row.style.display = 'none';
+          continue;
+        }
+        const r = filtered[visibleIdx];
+        row.style.display = '';
+        row.style.top = `${visibleIdx * ROW_H}px`;
+        for (let c = 0; c < COLS.length; c++) {
+          const col = COLS[c];
+          const cell = cells[c];
+          const val = col.get(r);
+          if (val === null || val === undefined) {
+            cell.textContent = '–';
+            cell.classList.add('triage-td-missing');
+          } else {
+            cell.classList.remove('triage-td-missing');
+            if (col.id === 'unit') {
+              cell.textContent = String(val).slice(0, 10);
+              cell.title = val;
+            } else if (col.id === 'type') {
+              cell.textContent = TYPE_LABELS[val] || val;
+              cell.className = `triage-td triage-type triage-type-${val}`;
+            } else if (col.num) {
+              cell.textContent = formatNumber(val);
+            } else {
+              cell.textContent = val;
+              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
+                cell.title = val;
+              }
+            }
+          }
+        }
+      }
+    };
+
+    // -----------------------------------------------------------------------
+    // Rebuild the filtered index array. O(N), runs on every filter change.
+    // -----------------------------------------------------------------------
+    const refilter = () => {
+      const out = new Int32Array(total);
+      let n = 0;
+      const fPass = filters.pass;
+      const fName = filters.name;
+      const fFunc = filters.func;
+      const fSource = filters.source;
+      const fTypes = filters.types;
+      const useTypes = fTypes.size > 0;
+
+      for (let i = 0; i < total; i++) {
+        if (useTypes && !fTypes.has(columns.type[i])) continue;
+        if (fPass) {
+          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
+          if (!s.includes(fPass)) continue;
+        }
+        if (fName) {
+          const s = (strings.name[columns.name[i]] || '').toLowerCase();
+          if (!s.includes(fName)) continue;
+        }
+        if (fFunc) {
+          const fi = columns.function[i];
+          if (fi < 0) continue;
+          const s = (strings.function[fi] || '').toLowerCase();
+          if (!s.includes(fFunc)) continue;
+        }
+        if (fSource) {
+          const fi = columns.file[i];
+          if (fi < 0) continue;
+          const s = (strings.file[fi] || '').toLowerCase();
+          if (!s.includes(fSource)) continue;
+        }
+        out[n++] = i;
+      }
+      filtered = out;
+      filteredLen = n;
+      spacer.style.height = `${n * ROW_H}px`;
+      viewport.scrollTop = 0;
+      counter.textContent = n === total
+        ? `${formatNumber(total)} remarks`
+        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
+      if (sortColId) applySort();
+      renderVisible();
+    };
+
+    // -----------------------------------------------------------------------
+    // Sort the filtered index array in place, then re-render.
+    // -----------------------------------------------------------------------
+    const applySort = () => {
+      const col = COLS.find(c => c.id === sortColId);
+      if (!col) return;
+      const dir = sortDir;
+      const view = Array.from(filtered.subarray(0, filteredLen));
+      if (col.idx) {
+        // Numeric / index sort, fast path. -1 sentinels sort last regardless
+        // of direction so missing values don't crowd the top.
+        view.sort((a, b) => {
+          const va = col.idx(a);
+          const vb = col.idx(b);
+          if (va < 0 && vb < 0) return 0;
+          if (va < 0) return 1;
+          if (vb < 0) return -1;
+          return (va - vb) * dir;
+        });
+      } else {
+        // Lexicographic fallback for text-only columns without an .idx.
+        view.sort((a, b) => {
+          const va = (col.get(a) || '').toString();
+          const vb = (col.get(b) || '').toString();
+          return va.localeCompare(vb) * dir;
+        });
+      }
+      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
+    };
+
+    const onSort = (colId) => {
+      if (sortColId === colId) {
+        sortDir = -sortDir;
+      } else {
+        sortColId = colId;
+        sortDir = 1;
+      }
+      applySort();
+      // Update sort indicators in the header.
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (!ind) return;
+        if (c.id === sortColId) {
+          ind.textContent = sortDir === 1 ? '▲' : '▼';
+          th.classList.add('sorted');
+        } else {
+          ind.textContent = '';
+          th.classList.remove('sorted');
+        }
+      });
+      viewport.scrollTop = 0;
+      renderVisible();
+    };
+
+    const resetAll = () => {
+      filters.pass = filters.name = filters.func = filters.source = '';
+      filters.types.clear();
+      // Reset DOM
+      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
+      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
+      sortColId = null;
+      sortDir = 1;
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        th.classList.remove('sorted');
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (ind) ind.textContent = '';
+      });
+      refilter();
+    };
+
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
+
+    // Initial render — defer until the viewport is laid out in the document.
+    requestAnimationFrame(renderVisible);
+
+    return wrap;
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
index 8815611946571..3359acac5eab5 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
@@ -664,3 +664,54 @@ html.dark{
 @media(max-width:480px){
   .impact-grid{grid-template-columns:1fr}
 }
+
+/* Triage Grid — virtualised, filterable per-remark table.
+   Lives inside a .chart-section so the outer card chrome is inherited. */
+.triage-grid{padding:16px 18px}
+.triage-header-row{display:flex;align-items:center;gap:12px;margin-bottom:10px}
+.triage-header-row h3{margin:0;font-size:13px}
+.triage-counter{font-family:var(--mono);font-size:11px;color:var(--fg2)}
+.triage-reset{margin-left:auto;background:transparent;border:1px solid var(--border);border-radius:var(--r);padding:4px 10px;font-size:11px;color:var(--fg2);cursor:pointer}
+.triage-reset:hover{border-color:var(--accent);color:var(--accent)}
+
+.triage-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--r);margin-bottom:8px}
+.triage-input{flex:1;min-width:120px;padding:5px 8px;font-size:11px;font-family:var(--mono);background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)}
+.triage-input:focus{outline:none;border-color:var(--accent)}
+.triage-input::placeholder{color:var(--fg3)}
+
+.triage-chips{display:flex;gap:4px;flex-wrap:wrap}
+.triage-chip{font-size:10px;font-family:var(--mono);padding:4px 8px;border-radius:99px;border:1px solid var(--border);background:var(--bg);color:var(--fg2);cursor:pointer;transition:background var(--fast),color var(--fast),border-color var(--fast)}
+.triage-chip:hover{border-color:var(--accent);color:var(--fg)}
+.triage-chip.on{background:var(--accent);color:#fff;border-color:var(--accent)}
+
+.triage-thead{display:flex;align-items:center;border:1px solid var(--border);border-bottom:0;background:var(--bg2);font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);user-select:none;min-width:max-content;border-radius:var(--r) var(--r) 0 0}
+.triage-th{padding:8px 10px;flex-shrink:0;display:flex;align-items:center;gap:4px}
+.triage-th.right{justify-content:flex-end}
+.triage-th.sortable{cursor:pointer}
+.triage-th.sortable:hover{color:var(--fg)}
+.triage-th.sorted{color:var(--accent)}
+.triage-sort-indicator{font-size:8px;line-height:1}
+
+/* Virtualised body: a fixed-height viewport scrolling over a tall spacer
+   that holds the row pool absolutely-positioned at row * rowHeight. */
+.triage-viewport{position:relative;overflow-y:auto;overflow-x:auto;border:1px solid var(--border);border-radius:0 0 var(--r) var(--r);background:var(--bg)}
+.triage-spacer{position:relative;min-width:max-content}
+.triage-row{position:absolute;left:0;display:flex;align-items:center;border-bottom:1px solid var(--bg2);will-change:top;min-width:max-content}
+.triage-row:hover{background:var(--bg2)}
+.triage-td{padding:0 10px;flex-shrink:0;font-size:11px;line-height:1;color:var(--fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:inline-block}
+.triage-td.mono{font-family:var(--mono)}
+.triage-td.right{text-align:right}
+.triage-td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
+.triage-td-missing{color:var(--fg3)}
+
+/* Type pills — color-coded by remarks::Type. */
+.triage-type{font-family:var(--mono);font-size:10px;padding:2px 6px;border-radius:4px}
+.triage-type-passed{color:var(--green);background:rgba(90,200,138,.08)}
+.triage-type-missed{color:var(--orange);background:rgba(255,179,71,.10)}
+.triage-type-analysis{color:var(--teal);background:rgba(123,224,214,.10)}
+.triage-type-analysis-fp-commute{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-analysis-aliasing{color:var(--blue);background:rgba(127,179,232,.10)}
+.triage-type-failure{color:var(--red);background:rgba(255,107,110,.10)}
+.triage-type-unknown{color:var(--fg3);background:var(--bg2)}
+
+.triage-empty{position:absolute;inset:0;display:none;align-items:center;justify-content:center;color:var(--fg3);font-size:12px;pointer-events:none}
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 727c8ba8a2f9d..f801d9185423e 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -906,7 +906,355 @@ const RemarksView = {
         tableSection.appendChild(h('div', { class: 'top-units-wrap' }, table));
         container.appendChild(tableSection);
       }
+
+      // Full triage grid: virtualised, filterable, sortable view of every
+      // remark in the relational payload. Lives below the summary tables.
+      container.appendChild(this._renderTriageGrid(rel));
+    }
+  },
+
+  // Triage Grid — Phase 1B of the proposal, against the C++ relational
+  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
+  // of ~32 row elements floats over an absolute-positioned spacer so that
+  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
+  // integer columns first; strings are dereferenced only for display.
+  _renderTriageGrid(rel) {
+    const { columns, strings } = rel;
+    const total = rel.count || 0;
+
+    // Canonical lowercase type keys; index = remarks::Type enum value.
+    const TYPE_NAMES = [
+      'unknown', 'passed', 'missed', 'analysis',
+      'analysis-fp-commute', 'analysis-aliasing', 'failure',
+    ];
+    const TYPE_LABELS = {
+      'unknown': 'Unknown',
+      'passed': 'Passed',
+      'missed': 'Missed',
+      'analysis': 'Analysis',
+      'analysis-fp-commute': 'FP-Commute',
+      'analysis-aliasing': 'Aliasing',
+      'failure': 'Failure',
+    };
+
+    // Column descriptors. `key` maps to a getter that resolves the integer
+    // column to a displayable value (string for text cells, number for
+    // numeric cells, null for missing).
+    const COLS = [
+      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
+        idx: (i) => columns.unit ? columns.unit[i] : -1 },
+      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => strings.pass[columns.pass[i]] || '?',
+        idx: (i) => columns.pass[i] },
+      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => strings.name[columns.name[i]] || '?',
+        idx: (i) => columns.name[i] },
+      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
+        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
+        idx: (i) => columns.type[i] },
+      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
+        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
+        idx: (i) => columns.function[i] },
+      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
+        get: (i) => {
+          const fi = columns.file[i];
+          if (fi < 0) return null;
+          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
+          return `${file}:${columns.line[i]}:${columns.column[i]}`;
+        } },
+      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
+        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
+        idx: (i) => columns.hotness[i] },
+    ];
+
+    // Mutable state -------------------------------------------------------
+    let filtered = new Int32Array(total);
+    for (let i = 0; i < total; i++) filtered[i] = i;
+    let filteredLen = total;
+    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
+    let sortColId = null;
+    let sortDir = 1; // 1 = ascending, -1 = descending
+
+    // DOM -----------------------------------------------------------------
+    const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
+
+    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
+    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    wrap.appendChild(h('div', { class: 'triage-header-row' },
+      h('h3', { style: { margin: '0' } }, 'All Remarks'),
+      counter,
+      resetBtn,
+    ));
+
+    // Filter bar. Text inputs filter on a case-insensitive substring of the
+    // matching string column; type chips toggle a set of allowed type enum
+    // values; hotness slider filters on minimum hotness.
+    const filterBar = h('div', { class: 'triage-filter-bar' });
+    const textFields = [
+      { key: 'pass',   placeholder: 'pass…' },
+      { key: 'name',   placeholder: 'remark name…' },
+      { key: 'func',   placeholder: 'function…' },
+      { key: 'source', placeholder: 'source file…' },
+    ];
+    textFields.forEach(f => {
+      const inp = h('input', {
+        class: 'triage-input',
+        type: 'search',
+        placeholder: f.placeholder,
+        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
+      });
+      filterBar.appendChild(inp);
+    });
+
+    // Type chips — clickable on/off filters for each remarks::Type value.
+    const typeChipBox = h('div', { class: 'triage-chips' });
+    TYPE_NAMES.forEach((name, enumVal) => {
+      if (name === 'unknown') return; // hide unless they actually appear
+      const chip = h('button', {
+        class: `triage-chip triage-chip-${name}`,
+        title: `Toggle ${TYPE_LABELS[name]}`,
+        onClick: () => {
+          if (filters.types.has(enumVal)) {
+            filters.types.delete(enumVal);
+            chip.classList.remove('on');
+          } else {
+            filters.types.add(enumVal);
+            chip.classList.add('on');
+          }
+          refilter();
+        },
+      }, TYPE_LABELS[name]);
+      typeChipBox.appendChild(chip);
+    });
+    filterBar.appendChild(typeChipBox);
+    wrap.appendChild(filterBar);
+
+    // Header row (sortable columns).
+    const tHead = h('div', { class: 'triage-thead' });
+    const thEls = {};
+    COLS.forEach(col => {
+      const th = h('div', {
+        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
+        style: { width: col.width + 'px' },
+        onClick: col.sortable ? () => onSort(col.id) : null,
+      },
+        h('span', { class: 'triage-th-label' }, col.label),
+        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
+      );
+      thEls[col.id] = th;
+      tHead.appendChild(th);
+    });
+    wrap.appendChild(tHead);
+
+    // Virtualised viewport.
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
+
+    const viewport = h('div', {
+      class: 'triage-viewport',
+      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
+    });
+    const spacer = h('div', { class: 'triage-spacer' });
+    spacer.style.height = `${total * ROW_H}px`;
+    viewport.appendChild(spacer);
+
+    // Pre-allocate the row pool once. Each row is an absolutely-positioned
+    // flex container with one span per column. Scroll only mutates each
+    // span's textContent and the row's top position.
+    const pool = [];
+    for (let p = 0; p < POOL_SIZE; p++) {
+      const row = h('div', { class: 'triage-row' });
+      row.style.height = `${ROW_H}px`;
+      const cells = COLS.map(col => h('span', {
+        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
+        style: { width: col.width + 'px' },
+      }, ''));
+      cells.forEach(c => row.appendChild(c));
+      spacer.appendChild(row);
+      pool.push({ row, cells });
     }
+    wrap.appendChild(viewport);
+
+    // Empty-state element shown when filteredLen === 0.
+    const emptyEl = h('div', { class: 'triage-empty' },
+      'No remarks match the current filters.'
+    );
+    viewport.appendChild(emptyEl);
+
+    // -----------------------------------------------------------------------
+    // Render the visible window. Called on scroll, filter, sort.
+    // -----------------------------------------------------------------------
+    const renderVisible = () => {
+      const len = filteredLen;
+      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const scrollTop = viewport.scrollTop;
+      const first = Math.max(0, Math.floor(scrollTop / ROW_H));
+      for (let p = 0; p < pool.length; p++) {
+        const visibleIdx = first + p;
+        const { row, cells } = pool[p];
+        if (visibleIdx >= len) {
+          row.style.display = 'none';
+          continue;
+        }
+        const r = filtered[visibleIdx];
+        row.style.display = '';
+        row.style.top = `${visibleIdx * ROW_H}px`;
+        for (let c = 0; c < COLS.length; c++) {
+          const col = COLS[c];
+          const cell = cells[c];
+          const val = col.get(r);
+          if (val === null || val === undefined) {
+            cell.textContent = '–';
+            cell.classList.add('triage-td-missing');
+          } else {
+            cell.classList.remove('triage-td-missing');
+            if (col.id === 'unit') {
+              cell.textContent = String(val).slice(0, 10);
+              cell.title = val;
+            } else if (col.id === 'type') {
+              cell.textContent = TYPE_LABELS[val] || val;
+              cell.className = `triage-td triage-type triage-type-${val}`;
+            } else if (col.num) {
+              cell.textContent = formatNumber(val);
+            } else {
+              cell.textContent = val;
+              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
+                cell.title = val;
+              }
+            }
+          }
+        }
+      }
+    };
+
+    // -----------------------------------------------------------------------
+    // Rebuild the filtered index array. O(N), runs on every filter change.
+    // -----------------------------------------------------------------------
+    const refilter = () => {
+      const out = new Int32Array(total);
+      let n = 0;
+      const fPass = filters.pass;
+      const fName = filters.name;
+      const fFunc = filters.func;
+      const fSource = filters.source;
+      const fTypes = filters.types;
+      const useTypes = fTypes.size > 0;
+
+      for (let i = 0; i < total; i++) {
+        if (useTypes && !fTypes.has(columns.type[i])) continue;
+        if (fPass) {
+          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
+          if (!s.includes(fPass)) continue;
+        }
+        if (fName) {
+          const s = (strings.name[columns.name[i]] || '').toLowerCase();
+          if (!s.includes(fName)) continue;
+        }
+        if (fFunc) {
+          const fi = columns.function[i];
+          if (fi < 0) continue;
+          const s = (strings.function[fi] || '').toLowerCase();
+          if (!s.includes(fFunc)) continue;
+        }
+        if (fSource) {
+          const fi = columns.file[i];
+          if (fi < 0) continue;
+          const s = (strings.file[fi] || '').toLowerCase();
+          if (!s.includes(fSource)) continue;
+        }
+        out[n++] = i;
+      }
+      filtered = out;
+      filteredLen = n;
+      spacer.style.height = `${n * ROW_H}px`;
+      viewport.scrollTop = 0;
+      counter.textContent = n === total
+        ? `${formatNumber(total)} remarks`
+        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
+      if (sortColId) applySort();
+      renderVisible();
+    };
+
+    // -----------------------------------------------------------------------
+    // Sort the filtered index array in place, then re-render.
+    // -----------------------------------------------------------------------
+    const applySort = () => {
+      const col = COLS.find(c => c.id === sortColId);
+      if (!col) return;
+      const dir = sortDir;
+      const view = Array.from(filtered.subarray(0, filteredLen));
+      if (col.idx) {
+        // Numeric / index sort, fast path. -1 sentinels sort last regardless
+        // of direction so missing values don't crowd the top.
+        view.sort((a, b) => {
+          const va = col.idx(a);
+          const vb = col.idx(b);
+          if (va < 0 && vb < 0) return 0;
+          if (va < 0) return 1;
+          if (vb < 0) return -1;
+          return (va - vb) * dir;
+        });
+      } else {
+        // Lexicographic fallback for text-only columns without an .idx.
+        view.sort((a, b) => {
+          const va = (col.get(a) || '').toString();
+          const vb = (col.get(b) || '').toString();
+          return va.localeCompare(vb) * dir;
+        });
+      }
+      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
+    };
+
+    const onSort = (colId) => {
+      if (sortColId === colId) {
+        sortDir = -sortDir;
+      } else {
+        sortColId = colId;
+        sortDir = 1;
+      }
+      applySort();
+      // Update sort indicators in the header.
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (!ind) return;
+        if (c.id === sortColId) {
+          ind.textContent = sortDir === 1 ? '▲' : '▼';
+          th.classList.add('sorted');
+        } else {
+          ind.textContent = '';
+          th.classList.remove('sorted');
+        }
+      });
+      viewport.scrollTop = 0;
+      renderVisible();
+    };
+
+    const resetAll = () => {
+      filters.pass = filters.name = filters.func = filters.source = '';
+      filters.types.clear();
+      // Reset DOM
+      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
+      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
+      sortColId = null;
+      sortDir = 1;
+      COLS.forEach(c => {
+        const th = thEls[c.id];
+        th.classList.remove('sorted');
+        const ind = th.querySelector('.triage-sort-indicator');
+        if (ind) ind.textContent = '';
+      });
+      refilter();
+    };
+
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
+
+    // Initial render — defer until the viewport is laid out in the document.
+    requestAnimationFrame(renderVisible);
+
+    return wrap;
   },
 };
 

>From 0aba340af3a54d2f5ac978a0e55c13382c13efef Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Thu, 28 May 2026 15:02:01 +0530
Subject: [PATCH 08/41] [llvm-advisor] lift remarks.detail per-unit cap from
 200 to 100000

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 llvm/tools/llvm-advisor/config/capabilities/catalog.json        | 2 +-
 .../src/Analysis/Inspection/RemarksDetailAnalyzer.cpp           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-advisor/config/capabilities/catalog.json b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
index cb80a552fc0c0..db27f0ca75fe2 100644
--- a/llvm/tools/llvm-advisor/config/capabilities/catalog.json
+++ b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
@@ -45,7 +45,7 @@
     {
       "id": "llvm.remarks.detail",
       "name": "Optimization remarks detail",
-      "version": "2",
+      "version": "3",
       "runner": "builtin.remarks_detail",
       "summary": "remarks detail requires an optimization remarks artifact",
       "readiness": "L1",
diff --git a/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
index 483dd50c7e756..e673299b94d91 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/Inspection/RemarksDetailAnalyzer.cpp
@@ -21,7 +21,7 @@ RemarksDetailAnalyzer::run(const CapabilityContext &Context) {
       [&](StringRef Path) -> Expected<std::unique_ptr<CapabilityResult>> {
         json::Array Items;
         bool Truncated = false;
-        constexpr size_t Limit = 200;
+        constexpr size_t Limit = 100000;
         if (Error E = foreachRemark(
                 Path, [&](const remarks::Remark &R) -> Error {
                   if (Items.size() >= Limit) {

>From 97ed77e1bdf9d4f1cdf7923618203238c0b2644f Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Thu, 28 May 2026 17:28:59 +0530
Subject: [PATCH 09/41] [llvm-advisor] split http response headers and body
 sends

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/HTTPServer.cpp            | 21 ++++++++++---------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index b450386bdd2aa..a285d56a87360 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -42,8 +42,8 @@ static std::string renderJSON(const json::Value &Value) {
 }
 
 #ifndef _WIN32
-static std::string makeRawHTTPResponse(unsigned Code, const char *ContentType,
-                                       StringRef Body, bool KeepAlive = false) {
+static std::string makeRawHTTPHeader(unsigned Code, const char *ContentType,
+                                     size_t BodyLen, bool KeepAlive = false) {
   std::string Out;
   raw_string_ostream OS(Out);
   const char *Reason =
@@ -52,12 +52,11 @@ static std::string makeRawHTTPResponse(unsigned Code, const char *ContentType,
           : (Code == 201 ? "Created" : (Code == 404 ? "Not Found" : "Error"));
   OS << "HTTP/1.1 " << Code << ' ' << Reason << "\r\n";
   OS << "Content-Type: " << ContentType << "\r\n";
-  OS << "Content-Length: " << Body.size() << "\r\n";
+  OS << "Content-Length: " << BodyLen << "\r\n";
   OS << "Access-Control-Allow-Origin: *\r\n";
   OS << "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n";
   OS << "Access-Control-Allow-Headers: Content-Type\r\n";
   OS << "Connection: " << (KeepAlive ? "keep-alive" : "close") << "\r\n\r\n";
-  OS << Body;
   OS.flush();
   return Out;
 }
@@ -877,9 +876,10 @@ Error llvm::advisor::HTTPServer::run() {
       // Auth check for API routes
       if (IsAPI && !checkAuth(Req.AuthHeader)) {
         Res = makeJSONErrorStr(401, "unauthorized");
-        std::string Out =
-            makeRawHTTPResponse(Res.Code, Res.ContentType, Res.Body);
-        (void)sendAll(FD, Out);
+        std::string Header =
+            makeRawHTTPHeader(Res.Code, Res.ContentType, Res.Body.size());
+        (void)sendAll(FD, Header);
+        (void)sendAll(FD, Res.Body);
         ::close(FD);
         return;
       }
@@ -954,9 +954,10 @@ Error llvm::advisor::HTTPServer::run() {
         Res = makeJSONErrorStr(405, "method not allowed");
       }
 
-      std::string Out = makeRawHTTPResponse(Res.Code, Res.ContentType, Res.Body,
-                                            Req.KeepAlive);
-      (void)sendAll(FD, Out);
+      std::string Header = makeRawHTTPHeader(Res.Code, Res.ContentType,
+                                             Res.Body.size(), Req.KeepAlive);
+      (void)sendAll(FD, Header);
+      (void)sendAll(FD, Res.Body);
       ::close(FD);
     });
   }

>From 940a44bd62f0e2f2a1e1db03bdd9e737e5df33b2 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Thu, 28 May 2026 18:19:09 +0530
Subject: [PATCH 10/41] [llvm-advisor] iterate units one at a time in
 relational handler

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/HTTPServer.cpp            | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index a285d56a87360..3f05236f01a12 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -636,18 +636,19 @@ class RelationalMerger {
 
 static HTTPResult handleGetRemarksRelational(CoreClient &Client,
                                              StringRef SnapID) {
-  SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
-  Expected<json::Array> Query = Client.querySnapshot(SnapID, Caps);
-  if (!Query)
-    return makeJSONError(400, Query.takeError());
+  SmallVector<UnitRecord, 64> Units =
+      Client.storage().metadata().listUnits(SnapID);
+  if (Units.empty())
+    return makeJSONErrorStr(404, "snapshot has no captured units");
 
+  const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
   RelationalMerger Merger;
-  for (const json::Value &UnitValue : *Query) {
-    const json::Object *UnitObj = UnitValue.getAsObject();
-    const json::Array *Results =
-        UnitObj ? UnitObj->getArray("results") : nullptr;
-    if (!Results)
+  for (const UnitRecord &Unit : Units) {
+    Expected<json::Array> Results = Client.queryUnit(Unit.ID, Caps);
+    if (!Results) {
+      consumeError(Results.takeError());
       continue;
+    }
     for (const json::Value &ResultValue : *Results) {
       const json::Object *ResultObj = ResultValue.getAsObject();
       if (!ResultObj)

>From 2ca2c67aec38c96b067b0b92b5d5fad9046e8ad4 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Fri, 29 May 2026 20:16:33 +0530
Subject: [PATCH 11/41] [llvm-advisor] stream-render relational merger to
 reduce peak RSS

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/HTTPServer.cpp            | 79 +++++++++++++------
 llvm/tools/llvm-advisor/src/Utils/JSON.cpp    | 13 +++
 llvm/tools/llvm-advisor/src/Utils/JSON.h      |  3 +
 3 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 3f05236f01a12..233a63bb9597f 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -512,6 +512,13 @@ class StringTable {
     return Out;
   }
 
+  void writeJSON(json::OStream &JOS) const {
+    JOS.arrayBegin();
+    for (const std::string &S : Strings)
+      JOS.value(S);
+    JOS.arrayEnd();
+  }
+
 private:
   std::vector<std::string> Strings;
   StringMap<unsigned> Index;
@@ -566,30 +573,37 @@ class RelationalMerger {
     }
   }
 
-  json::Object render(StringRef SnapshotID) {
-    return json::Object{
-        {"snapshot_id", SnapshotID.str()},
-        {"schema_version", 1},
-        {"count", static_cast<int64_t>(UnitColG.size())},
-        {"strings", json::Object{
-                        {"unit", Unit.toJSON()},
-                        {"pass", Pass.toJSON()},
-                        {"name", Name.toJSON()},
-                        {"function", Function.toJSON()},
-                        {"file", File.toJSON()},
-                    }},
-        {"columns", json::Object{
-                        {"unit", toArray(UnitColG)},
-                        {"pass", toArray(PassColG)},
-                        {"name", toArray(NameColG)},
-                        {"type", toArray(TypeColG)},
-                        {"function", toArray(FuncColG)},
-                        {"file", toArray(FileColG)},
-                        {"line", toArray(LineColG)},
-                        {"column", toArray(ColumnColG)},
-                        {"hotness", toArray(HotnessColG)},
-                    }},
-    };
+  void write(json::OStream &JOS, StringRef SnapshotID) const {
+    JOS.objectBegin();
+    JOS.attribute("snapshot_id", SnapshotID);
+    JOS.attribute("schema_version", 1);
+    JOS.attribute("count", static_cast<int64_t>(UnitColG.size()));
+
+    JOS.attributeBegin("strings");
+    JOS.objectBegin();
+    JOS.attributeBegin("unit");     Unit.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("pass");     Pass.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("name");     Name.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("function"); Function.writeJSON(JOS); JOS.attributeEnd();
+    JOS.attributeBegin("file");     File.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.objectEnd();
+    JOS.attributeEnd();
+
+    JOS.attributeBegin("columns");
+    JOS.objectBegin();
+    writeIntColumn(JOS, "unit",     UnitColG);
+    writeIntColumn(JOS, "pass",     PassColG);
+    writeIntColumn(JOS, "name",     NameColG);
+    writeIntColumn(JOS, "type",     TypeColG);
+    writeIntColumn(JOS, "function", FuncColG);
+    writeIntColumn(JOS, "file",     FileColG);
+    writeIntColumn(JOS, "line",     LineColG);
+    writeIntColumn(JOS, "column",   ColumnColG);
+    writeIntColumn(JOS, "hotness",  HotnessColG);
+    JOS.objectEnd();
+    JOS.attributeEnd();
+
+    JOS.objectEnd();
   }
 
 private:
@@ -627,6 +641,16 @@ class RelationalMerger {
     return Out;
   }
 
+  static void writeIntColumn(json::OStream &JOS, StringRef Name,
+                             ArrayRef<int64_t> Vs) {
+    JOS.attributeBegin(Name);
+    JOS.arrayBegin();
+    for (int64_t V : Vs)
+      JOS.value(V);
+    JOS.arrayEnd();
+    JOS.attributeEnd();
+  }
+
   StringTable Unit, Pass, Name, Function, File;
   std::vector<int64_t> UnitColG, PassColG, NameColG, TypeColG, FuncColG,
       FileColG, LineColG, ColumnColG, HotnessColG;
@@ -661,7 +685,12 @@ static HTTPResult handleGetRemarksRelational(CoreClient &Client,
     }
   }
 
-  return makeJSONSuccess(200, Merger.render(SnapID));
+  std::string Body;
+  raw_string_ostream OS(Body);
+  writeSuccessEnvelope(OS,
+                       [&](json::OStream &JOS) { Merger.write(JOS, SnapID); });
+  OS.flush();
+  return HTTPResult{200, "application/json", std::move(Body)};
 }
 
 static HTTPResult handleGetQueryUnit(CoreClient &Client, StringRef UnitID,
diff --git a/llvm/tools/llvm-advisor/src/Utils/JSON.cpp b/llvm/tools/llvm-advisor/src/Utils/JSON.cpp
index 6f12687428671..01b7f132475fe 100644
--- a/llvm/tools/llvm-advisor/src/Utils/JSON.cpp
+++ b/llvm/tools/llvm-advisor/src/Utils/JSON.cpp
@@ -97,3 +97,16 @@ json::Value llvm::advisor::errorEnvelope(StringRef Code, StringRef Message) {
                       {"status", "error"},
                       {"error", json::Object{{"code", Code}, {"message", Message}}}};
 }
+
+void llvm::advisor::writeSuccessEnvelope(
+    raw_ostream &OS, function_ref<void(json::OStream &)> WriteData) {
+  json::OStream JOS(OS);
+  JOS.object([&] {
+    JOS.attribute("request_id", uniqueRequestID());
+    JOS.attribute("timestamp_unix", unixNow());
+    JOS.attribute("status", "success");
+    JOS.attributeBegin("data");
+    WriteData(JOS);
+    JOS.attributeEnd();
+  });
+}
diff --git a/llvm/tools/llvm-advisor/src/Utils/JSON.h b/llvm/tools/llvm-advisor/src/Utils/JSON.h
index 75ce8f5ce899f..17da483911858 100644
--- a/llvm/tools/llvm-advisor/src/Utils/JSON.h
+++ b/llvm/tools/llvm-advisor/src/Utils/JSON.h
@@ -42,4 +42,7 @@ json::Value successEnvelope(json::Value Data);
 /// Wrap an error in a standard error envelope with request metadata.
 json::Value errorEnvelope(StringRef Code, StringRef Message);
 
+void writeSuccessEnvelope(raw_ostream &OS,
+                          function_ref<void(json::OStream &)> WriteData);
+
 } // namespace llvm::advisor

>From 7d1cd2fbe5a18bb5b989d81b8b1d94b570b512b7 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Fri, 29 May 2026 20:35:51 +0530
Subject: [PATCH 12/41] [llvm-advisor] extract StringTable into shared
 RemarksRelationalSchema header

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../Analysis/IR/RemarksRelationalAnalyzer.cpp | 26 +------
 .../src/Analysis/IR/RemarksRelationalSchema.h | 58 +++++++++++++++
 .../src/Client/HTTP/HTTPServer.cpp            | 70 ++++---------------
 3 files changed, 72 insertions(+), 82 deletions(-)
 create mode 100644 llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h

diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
index db4a8c673a843..d930b55bb0bec 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
@@ -1,35 +1,13 @@
 
 #include "Analysis/IR/RemarksRelationalAnalyzer.h"
+#include "Analysis/IR/RemarksRelationalSchema.h"
 #include "Analysis/RemarksAnalysisUtils.h"
-#include "llvm/ADT/StringMap.h"
 
 using namespace llvm;
 using namespace llvm::advisor;
 
 namespace {
 
-class StringTable {
-public:
-  unsigned getOrAdd(StringRef S) {
-    auto [It, Inserted] = Index.try_emplace(S, Strings.size());
-    if (Inserted)
-      Strings.emplace_back(S.str());
-    return It->second;
-  }
-
-  json::Array toJSON() const {
-    json::Array Out;
-    Out.reserve(Strings.size());
-    for (const std::string &S : Strings)
-      Out.push_back(S);
-    return Out;
-  }
-
-private:
-  std::vector<std::string> Strings;
-  StringMap<unsigned> Index;
-};
-
 class RelationalBuilder {
 public:
   void visit(const remarks::Remark &R) {
@@ -90,7 +68,7 @@ class RelationalBuilder {
     return Out;
   }
 
-  StringTable Pass, Name, Function, File;
+  RelationalStringTable Pass, Name, Function, File;
   std::vector<int64_t> PassCol, NameCol, TypeCol, FunctionCol, FileCol, LineCol,
       ColumnCol, HotnessCol;
 };
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h
new file mode 100644
index 0000000000000..3c1e5fcf1b9da
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h
@@ -0,0 +1,58 @@
+
+#ifndef LLVM_TOOLS_LLVM_ADVISOR_REMARKSRELATIONALSCHEMA_H
+#define LLVM_TOOLS_LLVM_ADVISOR_REMARKSRELATIONALSCHEMA_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/JSON.h"
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+class RelationalStringTable {
+public:
+  unsigned getOrAdd(StringRef S) {
+    auto [It, Inserted] = Index.try_emplace(S, Strings.size());
+    if (Inserted)
+      Strings.emplace_back(S.str());
+    return It->second;
+  }
+
+  json::Array toJSON() const {
+    json::Array Out;
+    Out.reserve(Strings.size());
+    for (const std::string &S : Strings)
+      Out.push_back(S);
+    return Out;
+  }
+
+  void writeJSON(json::OStream &JOS) const {
+    JOS.arrayBegin();
+    for (const std::string &S : Strings)
+      JOS.value(S);
+    JOS.arrayEnd();
+  }
+
+private:
+  std::vector<std::string> Strings;
+  StringMap<unsigned> Index;
+};
+
+inline void writeInt64Column(json::OStream &JOS, StringRef Name,
+                             ArrayRef<int64_t> Vs) {
+  JOS.attributeBegin(Name);
+  JOS.arrayBegin();
+  for (int64_t V : Vs)
+    JOS.value(V);
+  JOS.arrayEnd();
+  JOS.attributeEnd();
+}
+
+} // namespace advisor
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_ADVISOR_REMARKSRELATIONALSCHEMA_H
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 233a63bb9597f..8022a90634508 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "Analysis/IR/RemarksRelationalSchema.h"
 #include "Client/HTTP/HTTPServer.h"
 #include "Client/HTTP/Handlers/StaticHandler.h"
 #include "Utils/JSON.h"
@@ -495,35 +496,6 @@ static HTTPResult handleGetSummary(CoreClient &Client, StringRef SnapID) {
 
 namespace {
 
-class StringTable {
-public:
-  unsigned getOrAdd(StringRef S) {
-    auto [It, Inserted] = Index.try_emplace(S, Strings.size());
-    if (Inserted)
-      Strings.emplace_back(S.str());
-    return It->second;
-  }
-
-  json::Array toJSON() const {
-    json::Array Out;
-    Out.reserve(Strings.size());
-    for (const std::string &S : Strings)
-      Out.push_back(S);
-    return Out;
-  }
-
-  void writeJSON(json::OStream &JOS) const {
-    JOS.arrayBegin();
-    for (const std::string &S : Strings)
-      JOS.value(S);
-    JOS.arrayEnd();
-  }
-
-private:
-  std::vector<std::string> Strings;
-  StringMap<unsigned> Index;
-};
-
 class RelationalMerger {
 public:
 
@@ -591,15 +563,15 @@ class RelationalMerger {
 
     JOS.attributeBegin("columns");
     JOS.objectBegin();
-    writeIntColumn(JOS, "unit",     UnitColG);
-    writeIntColumn(JOS, "pass",     PassColG);
-    writeIntColumn(JOS, "name",     NameColG);
-    writeIntColumn(JOS, "type",     TypeColG);
-    writeIntColumn(JOS, "function", FuncColG);
-    writeIntColumn(JOS, "file",     FileColG);
-    writeIntColumn(JOS, "line",     LineColG);
-    writeIntColumn(JOS, "column",   ColumnColG);
-    writeIntColumn(JOS, "hotness",  HotnessColG);
+    writeInt64Column(JOS, "unit",     UnitColG);
+    writeInt64Column(JOS, "pass",     PassColG);
+    writeInt64Column(JOS, "name",     NameColG);
+    writeInt64Column(JOS, "type",     TypeColG);
+    writeInt64Column(JOS, "function", FuncColG);
+    writeInt64Column(JOS, "file",     FileColG);
+    writeInt64Column(JOS, "line",     LineColG);
+    writeInt64Column(JOS, "column",   ColumnColG);
+    writeInt64Column(JOS, "hotness",  HotnessColG);
     JOS.objectEnd();
     JOS.attributeEnd();
 
@@ -609,7 +581,7 @@ class RelationalMerger {
 private:
 
   static std::vector<int64_t> remapStrings(const json::Object *Strs,
-                                           StringRef Field, StringTable &Dst) {
+                                           StringRef Field, RelationalStringTable &Dst) {
     std::vector<int64_t> Map;
     const json::Array *Arr = Strs->getArray(Field);
     if (!Arr)
@@ -633,25 +605,7 @@ class RelationalMerger {
     return Map[Local];
   }
 
-  static json::Array toArray(ArrayRef<int64_t> Vs) {
-    json::Array Out;
-    Out.reserve(Vs.size());
-    for (int64_t V : Vs)
-      Out.push_back(V);
-    return Out;
-  }
-
-  static void writeIntColumn(json::OStream &JOS, StringRef Name,
-                             ArrayRef<int64_t> Vs) {
-    JOS.attributeBegin(Name);
-    JOS.arrayBegin();
-    for (int64_t V : Vs)
-      JOS.value(V);
-    JOS.arrayEnd();
-    JOS.attributeEnd();
-  }
-
-  StringTable Unit, Pass, Name, Function, File;
+  RelationalStringTable Unit, Pass, Name, Function, File;
   std::vector<int64_t> UnitColG, PassColG, NameColG, TypeColG, FuncColG,
       FileColG, LineColG, ColumnColG, HotnessColG;
 };

>From b2027c1abed1a4bb2e05ede887a8b9de2b1f0a44 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 30 May 2026 03:19:51 +0530
Subject: [PATCH 13/41] [llvm-advisor] intercept version-mismatch errors in
 foreachRemark

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Analysis/RemarksAnalysisUtils.cpp     | 26 +++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
index 85a731c91c161..2db3a32b585a7 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/RemarksAnalysisUtils.cpp
@@ -34,6 +34,28 @@ ArrayRef<StringRef> llvm::advisor::allRemarkTypeKeys() {
   return Keys;
 }
 
+static Error maybeUpgradeVersionError(Error E, StringRef Path) {
+  std::string Msg = toString(std::move(E));
+  if (Msg.find("Unsupported remark container version") != std::string::npos ||
+      Msg.find("Unsupported remark version in container") != std::string::npos) {
+    std::string Full;
+    raw_string_ostream OS(Full);
+    OS << "Remarks file '" << Path
+       << "' was produced by an incompatible LLVM toolchain. " << Msg
+       << "  Please rebuild the project with a matching LLVM version, or "
+       << "regenerate the remarks with the same LLVM used by llvm-advisor.";
+    OS.flush();
+    return createStringError(std::make_error_code(std::errc::invalid_argument),
+                             Full);
+  }
+  std::string Full;
+  raw_string_ostream OS(Full);
+  OS << "Error parsing remarks from '" << Path << "': " << Msg;
+  OS.flush();
+  return createStringError(std::make_error_code(std::errc::invalid_argument),
+                           Full);
+}
+
 Error llvm::advisor::foreachRemark(StringRef Path, RemarkVisitor Visitor) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> MB = MemoryBuffer::getFile(Path);
   if (!MB)
@@ -44,7 +66,7 @@ Error llvm::advisor::foreachRemark(StringRef Path, RemarkVisitor Visitor) {
       remarks::createRemarkParser(remarks::Format::Auto,
                                    MB.get()->getBuffer());
   if (!Parser)
-    return Parser.takeError();
+    return maybeUpgradeVersionError(Parser.takeError(), Path);
 
   while (true) {
     Expected<std::unique_ptr<remarks::Remark>> Next = (*Parser)->next();
@@ -54,7 +76,7 @@ Error llvm::advisor::foreachRemark(StringRef Path, RemarkVisitor Visitor) {
         consumeError(std::move(E));
         break;
       }
-      return E;
+      return maybeUpgradeVersionError(std::move(E), Path);
     }
     if (Error E = Visitor(**Next))
       return E;

>From 9de1a61cf7c10f874eec3da593c87be83111769b Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 14 Jun 2026 05:39:36 +0530
Subject: [PATCH 14/41] [advisor] discover .opt.bitstream files in
 findRemarksPath

---
 llvm/tools/llvm-advisor/src/Analysis/AnalyzerBase.cpp        | 5 ++++-
 .../llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp   | 2 +-
 llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp             | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/AnalyzerBase.cpp b/llvm/tools/llvm-advisor/src/Analysis/AnalyzerBase.cpp
index 98f13bc53fff1..68aeb72381a04 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/AnalyzerBase.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/AnalyzerBase.cpp
@@ -25,6 +25,9 @@ std::string llvm::advisor::findRemarksPath(const CapabilityContext &Context) {
 
   // 1. Source-adjacent: replace extension in-place (cmake -save-temps style).
   SmallString<256> FromSource(Context.SourcePath);
+  sys::path::replace_extension(FromSource, "opt.bitstream");
+  if (sys::fs::exists(FromSource))
+    return std::string(FromSource);
   sys::path::replace_extension(FromSource, "opt.yaml");
   if (sys::fs::exists(FromSource))
     return std::string(FromSource);
@@ -36,7 +39,7 @@ std::string llvm::advisor::findRemarksPath(const CapabilityContext &Context) {
     StringRef Stem = sys::path::stem(Context.SourcePath);
 
     // 2. Build-dir/<stem>.opt.yaml — the most common clang layout.
-    for (StringRef Ext : {"opt.yaml", "opt.json"}) {
+    for (StringRef Ext : {"opt.bitstream", "opt.yaml", "opt.json"}) {
       SmallString<256> P(Context.WorkingDirectory);
       sys::path::append(P, Stem);
       sys::path::replace_extension(P, Ext);
diff --git a/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp b/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
index b26a50c274d79..48d9a6f7514ab 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
@@ -402,7 +402,7 @@ llvm::advisor::emitOptRemarks(const CapabilityContext &Context,
     return createStringError(EC, "failed to create temp object file");
 
   SmallVector<std::string, 8> ExtraArgs = {
-      "-c", "-o", ObjPath.str().str(), "-fsave-optimization-record=yaml",
+      "-c", "-o", ObjPath.str().str(), "-fsave-optimization-record=bitstream",
       ("-foptimization-record-file=" + OutPath).str()};
   Expected<std::string> Result =
       runCompilerInvocation(Context, ExtraArgs, OutPath);
diff --git a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
index 0748620d41bd1..5f48a94ac9034 100644
--- a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
+++ b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
@@ -146,7 +146,7 @@ Error synthesizeArtifacts(CapabilityContext &Context, StringRef StoreRoot,
 
   if (NeedsRemarks && findRemarksPath(Context).empty()) {
     SmallString<256> RemarksOut(ArtDir);
-    sys::path::append(RemarksOut, "remarks.opt.yaml");
+    sys::path::append(RemarksOut, "remarks.opt.bitstream");
     if (auto Path = emitOptRemarks(Context, RemarksOut))
       Context.RemarksPath = *Path;
     else

>From 88213836e7281e01599eab0a1bfa51a04328c2e6 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:02:57 +0530
Subject: [PATCH 15/41] [llvm-advisor] resolve real path for
 compile_commands.json

Use sys::fs::real_path in findBuildDir so that symlinked or relative
paths to compile_commands.json resolve to their actual directory.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
index 1185991c53b06..af4f9ee89c7a6 100644
--- a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
@@ -102,6 +102,9 @@ static std::string findBuildDir(StringRef StartDir) {
     SmallString<256> Candidate(StartDir);
     sys::path::append(Candidate, Sub, "compile_commands.json");
     if (sys::fs::exists(Candidate)) {
+      SmallString<256> RealPath;
+      if (!sys::fs::real_path(Candidate, RealPath))
+        return std::string(sys::path::parent_path(RealPath));
       sys::path::remove_filename(Candidate);
       return std::string(Candidate);
     }
@@ -112,8 +115,12 @@ static std::string findBuildDir(StringRef StartDir) {
   for (int Depth = 0; Depth < 16; ++Depth) {
     SmallString<256> Candidate(Dir);
     sys::path::append(Candidate, "compile_commands.json");
-    if (sys::fs::exists(Candidate))
+    if (sys::fs::exists(Candidate)) {
+      SmallString<256> RealPath;
+      if (!sys::fs::real_path(Candidate, RealPath))
+        return std::string(sys::path::parent_path(RealPath));
       return std::string(Dir);
+    }
     StringRef Parent = sys::path::parent_path(Dir);
     if (Parent == Dir)
       break;

>From 96bb922d539c529b358189306eda36bab019514a Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:03:12 +0530
Subject: [PATCH 16/41] [llvm-advisor] add hotspot analyzer and capability

Add RemarksHotspotAnalyzer that aggregates optimization remarks by
function, file, and line to identify hotspots. Register the
builtin.remarks_hotspot runner and add the llvm.remarks.hotspot
capability to the catalog with dependency on llvm.remarks.summary.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../config/capabilities/catalog.json          | 11 +++
 .../Analysis/IR/RemarksHotspotAnalyzer.cpp    | 98 +++++++++++++++++++
 .../src/Analysis/IR/RemarksHotspotAnalyzer.h  | 24 +++++
 .../src/Capability/CapabilityRegistry.cpp     |  3 +
 4 files changed, 136 insertions(+)
 create mode 100644 llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
 create mode 100644 llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.h

diff --git a/llvm/tools/llvm-advisor/config/capabilities/catalog.json b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
index db27f0ca75fe2..5f7ffb8e06219 100644
--- a/llvm/tools/llvm-advisor/config/capabilities/catalog.json
+++ b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
@@ -42,6 +42,17 @@
         "llvm.remarks.summary"
       ]
     },
+    {
+      "id": "llvm.remarks.hotspot",
+      "name": "Optimization remarks hotspots",
+      "version": "1",
+      "runner": "builtin.remarks_hotspot",
+      "summary": "hotspot analysis requires an optimization remarks artifact",
+      "readiness": "L1",
+      "dependencies": [
+        "llvm.remarks.summary"
+      ]
+    },
     {
       "id": "llvm.remarks.detail",
       "name": "Optimization remarks detail",
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
new file mode 100644
index 0000000000000..b0ac7482c5ebe
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
@@ -0,0 +1,98 @@
+//===--- RemarksHotspotAnalyzer.cpp - LLVM Advisor -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Analysis/IR/RemarksHotspotAnalyzer.h"
+#include "Analysis/RemarksAnalysisUtils.h"
+#include "llvm/Support/JSON.h"
+
+using namespace llvm;
+using namespace llvm::advisor;
+
+namespace {
+
+struct HotspotEntry {
+  std::string Function;
+  std::string File;
+  int64_t Line;
+  int64_t Count;
+  int64_t MaxHotness;
+};
+
+class HotspotBuilder {
+public:
+  void visit(const remarks::Remark &R) {
+    std::string Key = (R.FunctionName.empty() ? "<unknown>" : R.FunctionName.str()) + ":" +
+                      (R.Loc ? R.Loc->SourceFilePath.str() : "") + ":" +
+                      (R.Loc ? std::to_string(R.Loc->SourceLine) : "0");
+    
+    auto &Entry = Hotspots[Key];
+    if (Entry.Function.empty()) {
+      Entry.Function = R.FunctionName.empty() ? "<unknown>" : R.FunctionName.str();
+      Entry.File = R.Loc ? R.Loc->SourceFilePath.str() : "";
+      Entry.Line = R.Loc ? static_cast<int64_t>(R.Loc->SourceLine) : 0;
+      Entry.Count = 0;
+      Entry.MaxHotness = -1;
+    }
+    Entry.Count++;
+    if (R.Hotness && static_cast<int64_t>(*R.Hotness) > Entry.MaxHotness)
+      Entry.MaxHotness = static_cast<int64_t>(*R.Hotness);
+  }
+
+  json::Object render(StringRef Path) {
+    std::vector<HotspotEntry> Result;
+    for (auto &KV : Hotspots)
+      Result.push_back(KV.second);
+
+    // Sort by count descending
+    llvm::sort(Result, [](const HotspotEntry &A, const HotspotEntry &B) {
+      return A.Count > B.Count;
+    });
+
+    json::Array HotspotArray;
+    for (const auto &H : Result) {
+      json::Object Obj;
+      Obj["function"] = H.Function;
+      Obj["file"] = H.File;
+      Obj["line"] = H.Line;
+      Obj["count"] = H.Count;
+      Obj["max_hotness"] = H.MaxHotness;
+      HotspotArray.push_back(std::move(Obj));
+    }
+
+    return json::Object{
+        {"available", true},
+        {"capability", "llvm.remarks.hotspot"},
+        {"hotspots", std::move(HotspotArray)},
+        {"count", static_cast<int64_t>(Result.size())},
+        {"remarks_path", Path.str()},
+    };
+  }
+
+private:
+  llvm::StringMap<HotspotEntry> Hotspots;
+};
+
+} // namespace
+
+Expected<std::unique_ptr<CapabilityResult>>
+RemarksHotspotAnalyzer::run(const CapabilityContext &Context) {
+  StringRef CapID = getCapabilityID();
+  StringRef UnitID = Context.Unit.ID;
+  return withRemarksFile(
+      Context, CapID, UnitID,
+      [&](StringRef Path) -> Expected<std::unique_ptr<CapabilityResult>> {
+        HotspotBuilder Builder;
+        if (Error E = foreachRemark(
+                Path, [&](const remarks::Remark &R) -> Error {
+                  Builder.visit(R);
+                  return Error::success();
+                }))
+          return std::move(E);
+        return makeJSONResult(CapID, UnitID, Builder.render(Path));
+      });
+}
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.h b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.h
new file mode 100644
index 0000000000000..005a70218d6a8
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.h
@@ -0,0 +1,24 @@
+//===--- RemarksHotspotAnalyzer.h - LLVM Advisor -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "Analysis/AnalyzerBase.h"
+
+namespace llvm::advisor {
+
+class RemarksHotspotAnalyzer final : public CapabilityRunner {
+public:
+  StringRef getCapabilityID() const override {
+    return "llvm.remarks.hotspot";
+  }
+  Expected<std::unique_ptr<CapabilityResult>>
+  run(const CapabilityContext &Context) override;
+};
+
+} // namespace llvm::advisor
diff --git a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
index 78610bb47d1a2..4c98f7c64b7a5 100644
--- a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
+++ b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
@@ -15,6 +15,7 @@
 #include "Analysis/IR/RemarksMixAnalyzer.h"
 #include "Analysis/IR/RemarksRelationalAnalyzer.h"
 #include "Analysis/IR/RemarksSizeDiffAnalyzer.h"
+#include "Analysis/IR/RemarksHotspotAnalyzer.h"
 #include "Analysis/Inspection/RemarksDetailAnalyzer.h"
 #include "Utils/JSON.h"
 #include "llvm/Support/FileSystem.h"
@@ -228,6 +229,8 @@ void CapabilityRegistry::addBuiltinRunners() {
                          std::make_unique<RemarksSizeDiffAnalyzer>()));
   consumeError(addRunner("builtin.remarks_relational",
                          std::make_unique<RemarksRelationalAnalyzer>()));
+  consumeError(addRunner("builtin.remarks_hotspot",
+                         std::make_unique<RemarksHotspotAnalyzer>()));
   consumeError(addRunner("builtin.remarks_detail",
                          std::make_unique<RemarksDetailAnalyzer>()));
 }

>From fc61df154a4674bd4d6c2c899b7212440689d3d7 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:03:26 +0530
Subject: [PATCH 17/41] [llvm-advisor] add heatmap UI and navigation

Add HeatmapView to render hotspot tables from llvm.remarks.hotspot.
Add heatmap icon to core.js and sidebar navigation to shell.js with
keyboard shortcut g h. Register the /heatmap route in bundle.py and
index.html.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundle.py          |  4 +
 .../src/Client/HTTP/Assets/core.js            |  3 +-
 .../src/Client/HTTP/Assets/index.html         |  1 +
 .../src/Client/HTTP/Assets/shell.js           |  2 +
 .../src/Client/HTTP/Assets/views.js           | 81 +++++++++++++++++++
 5 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
index eb9d32bf35ed2..11a0dcfc6333f 100755
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
@@ -67,6 +67,10 @@ def main():
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
+      Router.register('/timeline', () => TimelineView.render());
+      Router.register('/insights', () => InsightsView.render());
+      Router.register('/remarks', () => RemarksView.render());
+      Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index 7acb09c8d136d..5ebb899f6dd87 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -11,6 +11,7 @@ const Icons = {
   timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
   insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
+  heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -221,7 +222,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
index ed7007aeb6896..ccd0f67b22acf 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
@@ -27,6 +27,7 @@
       Router.register('/timeline', () => TimelineView.render());
       Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
+      Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/settings', () => SettingsView.render());
 
       Shell.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
index 7ad33b4065b0b..2e5c9570fc89b 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
@@ -78,6 +78,7 @@ const Shell = {
       { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
+      { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -205,6 +206,7 @@ const CommandPalette = {
     { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
+    { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index f801d9185423e..5045b0b2ce8c8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1454,3 +1454,84 @@ const SettingsView = {
     return card;
   },
 };
+
+/* ============================================================
+   LLVM Advisor — Heatmap View
+   ============================================================ */
+
+const HeatmapView = {
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to view hotspots.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    const loading = h('div', { class: 'text-muted' }, 'Loading hotspots...');
+    container.appendChild(loading);
+    Shell.renderMain(container);
+
+    const res = await API.querySnapshot(snap.id, ['llvm.remarks.hotspot']);
+    if (!res.ok) {
+      container.innerHTML = '';
+      container.appendChild(UI.errorCard(res.error || 'Failed to load hotspots'));
+      return;
+    }
+
+    const results = Array.isArray(res.data) ? res.data : [];
+    const allHotspots = results.flatMap(unit => {
+      const unitResults = Array.isArray(unit.results) ? unit.results : [];
+      return unitResults.flatMap(r => {
+        if (r.capability === 'llvm.remarks.hotspot' && r.value && r.value.hotspots) {
+          return r.value.hotspots.map(h => ({
+            ...h,
+            unit: unit.source_path || unit.unit_id || '',
+          }));
+        }
+        return [];
+      });
+    });
+
+    container.innerHTML = '';
+
+    if (!allHotspots.length) {
+      container.appendChild(UI.emptyCard('No hotspots found', 'No optimization remark hotspots were detected for this snapshot.'));
+      return;
+    }
+
+    // Sort by count descending
+    allHotspots.sort((a, b) => b.count - a.count);
+
+    // Render table
+    const table = h('table', { class: 'data-table' });
+    const thead = h('thead', {},
+      h('tr', {},
+        h('th', {}, 'Function'),
+        h('th', {}, 'File'),
+        h('th', {}, 'Line'),
+        h('th', {}, 'Count'),
+        h('th', {}, 'Max Hotness')
+      )
+    );
+    table.appendChild(thead);
+
+    const tbody = h('tbody');
+    allHotspots.forEach(hotspot => {
+      const row = h('tr', {},
+        h('td', { class: 'mono' }, hotspot.function || ''),
+        h('td', { class: 'mono' }, hotspot.file || ''),
+        h('td', { class: 'mono' }, String(hotspot.line || '')),
+        h('td', {}, String(hotspot.count || 0)),
+        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
+      );
+      tbody.appendChild(row);
+    });
+    table.appendChild(tbody);
+
+    container.appendChild(table);
+  },
+};

>From 76c534ebf2ea6bc01b485cc55a3b17711b5ba55a Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:03:53 +0530
Subject: [PATCH 18/41] [llvm-advisor] show relational grid in unit detail
 remarks tab

When llvm.remarks.relational is available, render the full triage grid
in the unit detail Remarks tab instead of the limited findingList.
Add llvm.remarks.relational to the default capabilities queried for
units so the relational data is fetched.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/unit-detail.js     | 84 ++++++++++++++++++-
 1 file changed, 80 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
index 6501efd72e938..64c4b5cc766ee 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
@@ -55,7 +55,7 @@ const UnitDetailView = {
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Remarks', 'Artifacts'];
+    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -116,7 +116,19 @@ const UnitDetailView = {
 
     const controls = h('div', { class: 'cap-pills' });
     const body = h('div', { class: 'capability-stack' });
-    const modes = [['remarks', 'Remarks']];
+    const modes = [
+      ['signals', 'Signals'],
+      ['ir', 'IR'],
+      ['cfg', 'CFG'],
+      ['dom', 'Dom'],
+      ['loop', 'Loops'],
+      ['callgraph', 'Call Graph'],
+      ['asm', 'Asm'],
+      ['mca', 'MCA'],
+      ['remarks', 'Remarks'],
+      ['debug', 'Debug'],
+      ['passes', 'Passes'],
+    ];
 
     const loadMode = async (mode, pill) => {
       Array.from(controls.children).forEach(node => node.classList.remove('available'));
@@ -171,6 +183,10 @@ const UnitDetailView = {
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
     // Function list placeholder in sidebar
+    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
+      h('div', { class: 'rail-title' }, 'Functions'),
+      h('div', { class: 'rail-empty' }, 'Loading function list')
+    ));
   },
 
   addSection(parent, title, open, kvPairs) {
@@ -196,7 +212,30 @@ const UnitDetailView = {
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
+    if (tab === 'Diagnostics') {
+      const findings = state.results
+        .filter(r => r.capability.startsWith('clang.diag'))
+        .flatMap(r => r.findings);
+      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
+      const bySev = {};
+      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
+      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
+      return h('div', { class: 'capability-stack' },
+        chartData.length ? UI.barChart(chartData) : null,
+        UI.findingList(findings)
+      );
+    }
+
     if (tab === 'Remarks') {
+      const relResult = state.byCapability.get('llvm.remarks.relational');
+      if (relResult && relResult.available && relResult.value && relResult.value.columns) {
+        const v = relResult.value;
+        const rel = { count: v.count || 0, columns: v.columns || {}, strings: v.strings || {} };
+        const total = rel.count || 0;
+        const filtered = new Int32Array(total);
+        for (let i = 0; i < total; i++) filtered[i] = i;
+        return RemarksView._renderTriageGrid(rel, null, filtered, total);
+      }
       const findings = state.results
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
@@ -209,6 +248,13 @@ const UnitDetailView = {
       );
     }
 
+    if (tab === 'Functions') {
+      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
+      const rows = fnResult?.value?.functions || [];
+      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
+      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
+    }
+
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -226,6 +272,9 @@ const UnitDetailView = {
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
+        this.summaryCard('Functions', metrics.functions, 'neutral'),
+        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
+        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -249,9 +298,12 @@ const UnitDetailView = {
   },
 
   collectOverview(results) {
-    const metrics = { remarks: 0 };
+    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
+      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
+      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
+      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -261,7 +313,7 @@ const UnitDetailView = {
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['llvm.remarks.summary', 'llvm.remarks.detail'];
+      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -273,6 +325,30 @@ const UnitDetailView = {
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
+    // Populate function list in sidebar
+    const fnCard = sidebar.querySelector('#function-list-card');
+    results.forEach(r => {
+      const val = r.value;
+      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
+        if (fnCard) {
+          clearEl(fnCard);
+          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
+          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
+          const list = h('div', { class: 'fn-section' });
+          fns.slice(0, 50).forEach(fn => {
+            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
+              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
+              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
+            ));
+          });
+          if (fns.length > 50) {
+            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
+              `+ ${fns.length - 50} more…`));
+          }
+          fnCard.appendChild(list);
+        }
+      }
+    });
     if (refresh) refresh();
   },
 

>From ec06e7ada656f6cfe3c3bc3b010356a612e71673 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:04:07 +0530
Subject: [PATCH 19/41] [llvm-advisor] bundle heatmap view assets

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 99 ++++++++++++++++++-
 .../src/Client/HTTP/Assets/index_html.inc     | 99 ++++++++++++++++++-
 2 files changed, 194 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index e25cab904c6c4..ac7fd8cea08eb 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -743,6 +743,7 @@
   timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
   insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
+  heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -953,7 +954,7 @@
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2078,6 +2079,7 @@
       { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
+      { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2205,6 +2207,7 @@
     { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
+    { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -3301,6 +3304,15 @@
     }
 
     if (tab === 'Remarks') {
+      const relResult = state.byCapability.get('llvm.remarks.relational');
+      if (relResult && relResult.available && relResult.value && relResult.value.columns) {
+        const v = relResult.value;
+        const rel = { count: v.count || 0, columns: v.columns || {}, strings: v.strings || {} };
+        const total = rel.count || 0;
+        const filtered = new Int32Array(total);
+        for (let i = 0; i < total; i++) filtered[i] = i;
+        return RemarksView._renderTriageGrid(rel, null, filtered, total);
+      }
       const findings = state.results
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
@@ -3378,7 +3390,7 @@
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail'];
+      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -5197,6 +5209,87 @@
   },
 };
 
+/* ============================================================
+   LLVM Advisor — Heatmap View
+   ============================================================ */
+
+const HeatmapView = {
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to view hotspots.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    const loading = h('div', { class: 'text-muted' }, 'Loading hotspots...');
+    container.appendChild(loading);
+    Shell.renderMain(container);
+
+    const res = await API.querySnapshot(snap.id, ['llvm.remarks.hotspot']);
+    if (!res.ok) {
+      container.innerHTML = '';
+      container.appendChild(UI.errorCard(res.error || 'Failed to load hotspots'));
+      return;
+    }
+
+    const results = Array.isArray(res.data) ? res.data : [];
+    const allHotspots = results.flatMap(unit => {
+      const unitResults = Array.isArray(unit.results) ? unit.results : [];
+      return unitResults.flatMap(r => {
+        if (r.capability === 'llvm.remarks.hotspot' && r.value && r.value.hotspots) {
+          return r.value.hotspots.map(h => ({
+            ...h,
+            unit: unit.source_path || unit.unit_id || '',
+          }));
+        }
+        return [];
+      });
+    });
+
+    container.innerHTML = '';
+
+    if (!allHotspots.length) {
+      container.appendChild(UI.emptyCard('No hotspots found', 'No optimization remark hotspots were detected for this snapshot.'));
+      return;
+    }
+
+    // Sort by count descending
+    allHotspots.sort((a, b) => b.count - a.count);
+
+    // Render table
+    const table = h('table', { class: 'data-table' });
+    const thead = h('thead', {},
+      h('tr', {},
+        h('th', {}, 'Function'),
+        h('th', {}, 'File'),
+        h('th', {}, 'Line'),
+        h('th', {}, 'Count'),
+        h('th', {}, 'Max Hotness')
+      )
+    );
+    table.appendChild(thead);
+
+    const tbody = h('tbody');
+    allHotspots.forEach(hotspot => {
+      const row = h('tr', {},
+        h('td', { class: 'mono' }, hotspot.function || ''),
+        h('td', { class: 'mono' }, hotspot.file || ''),
+        h('td', { class: 'mono' }, String(hotspot.line || '')),
+        h('td', {}, String(hotspot.count || 0)),
+        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
+      );
+      tbody.appendChild(row);
+    });
+    table.appendChild(tbody);
+
+    container.appendChild(table);
+  },
+};
+
   </script>
   <script>
     (function() {
@@ -5206,6 +5299,8 @@
       Router.register('/compare', params => CompareView.render(params));
       Router.register('/timeline', () => TimelineView.render());
       Router.register('/insights', () => InsightsView.render());
+      Router.register('/remarks', () => RemarksView.render());
+      Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 516ef6614520b..9c16c70411dd4 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -746,6 +746,7 @@ const Icons = {
   timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
   insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
+  heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
@@ -956,7 +957,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2081,6 +2082,7 @@ const Shell = {
       { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
+      { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2208,6 +2210,7 @@ const CommandPalette = {
     { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
+    { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -3304,6 +3307,15 @@ const UnitDetailView = {
     }
 
     if (tab === 'Remarks') {
+      const relResult = state.byCapability.get('llvm.remarks.relational');
+      if (relResult && relResult.available && relResult.value && relResult.value.columns) {
+        const v = relResult.value;
+        const rel = { count: v.count || 0, columns: v.columns || {}, strings: v.strings || {} };
+        const total = rel.count || 0;
+        const filtered = new Int32Array(total);
+        for (let i = 0; i < total; i++) filtered[i] = i;
+        return RemarksView._renderTriageGrid(rel, null, filtered, total);
+      }
       const findings = state.results
         .filter(r => r.capability.includes('remarks'))
         .flatMap(r => r.findings);
@@ -3381,7 +3393,7 @@ const UnitDetailView = {
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail'];
+      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -5200,6 +5212,87 @@ const SettingsView = {
   },
 };
 
+/* ============================================================
+   LLVM Advisor — Heatmap View
+   ============================================================ */
+
+const HeatmapView = {
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
+
+    const snap = State.get('currentSnapshot');
+    if (!snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to view hotspots.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    const loading = h('div', { class: 'text-muted' }, 'Loading hotspots...');
+    container.appendChild(loading);
+    Shell.renderMain(container);
+
+    const res = await API.querySnapshot(snap.id, ['llvm.remarks.hotspot']);
+    if (!res.ok) {
+      container.innerHTML = '';
+      container.appendChild(UI.errorCard(res.error || 'Failed to load hotspots'));
+      return;
+    }
+
+    const results = Array.isArray(res.data) ? res.data : [];
+    const allHotspots = results.flatMap(unit => {
+      const unitResults = Array.isArray(unit.results) ? unit.results : [];
+      return unitResults.flatMap(r => {
+        if (r.capability === 'llvm.remarks.hotspot' && r.value && r.value.hotspots) {
+          return r.value.hotspots.map(h => ({
+            ...h,
+            unit: unit.source_path || unit.unit_id || '',
+          }));
+        }
+        return [];
+      });
+    });
+
+    container.innerHTML = '';
+
+    if (!allHotspots.length) {
+      container.appendChild(UI.emptyCard('No hotspots found', 'No optimization remark hotspots were detected for this snapshot.'));
+      return;
+    }
+
+    // Sort by count descending
+    allHotspots.sort((a, b) => b.count - a.count);
+
+    // Render table
+    const table = h('table', { class: 'data-table' });
+    const thead = h('thead', {},
+      h('tr', {},
+        h('th', {}, 'Function'),
+        h('th', {}, 'File'),
+        h('th', {}, 'Line'),
+        h('th', {}, 'Count'),
+        h('th', {}, 'Max Hotness')
+      )
+    );
+    table.appendChild(thead);
+
+    const tbody = h('tbody');
+    allHotspots.forEach(hotspot => {
+      const row = h('tr', {},
+        h('td', { class: 'mono' }, hotspot.function || ''),
+        h('td', { class: 'mono' }, hotspot.file || ''),
+        h('td', { class: 'mono' }, String(hotspot.line || '')),
+        h('td', {}, String(hotspot.count || 0)),
+        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
+      );
+      tbody.appendChild(row);
+    });
+    table.appendChild(tbody);
+
+    container.appendChild(table);
+  },
+};
+
   </script>
   <script>
     (function() {
@@ -5209,6 +5302,8 @@ const SettingsView = {
       Router.register('/compare', params => CompareView.render(params));
       Router.register('/timeline', () => TimelineView.render());
       Router.register('/insights', () => InsightsView.render());
+      Router.register('/remarks', () => RemarksView.render());
+      Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();

>From f1d84296ec11ef8681ceff48550bc957d47ecc81 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 15 Jun 2026 17:39:54 +0530
Subject: [PATCH 20/41] [llvm-advisor] demangle function names in relational
 and hotspot output

Use llvm::demangle() in RemarksRelationalAnalyzer and
RemarksHotspotAnalyzer so that mangled C++ function names are
presented as human-readable signatures in the UI.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Analysis/IR/RemarksHotspotAnalyzer.cpp           | 7 ++++++-
 .../src/Analysis/IR/RemarksRelationalAnalyzer.cpp        | 9 ++++++---
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
index b0ac7482c5ebe..9e0adbcf9a9da 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksHotspotAnalyzer.cpp
@@ -8,6 +8,7 @@
 
 #include "Analysis/IR/RemarksHotspotAnalyzer.h"
 #include "Analysis/RemarksAnalysisUtils.h"
+#include "llvm/Demangle/Demangle.h"
 #include "llvm/Support/JSON.h"
 
 using namespace llvm;
@@ -32,7 +33,11 @@ class HotspotBuilder {
     
     auto &Entry = Hotspots[Key];
     if (Entry.Function.empty()) {
-      Entry.Function = R.FunctionName.empty() ? "<unknown>" : R.FunctionName.str();
+      if (R.FunctionName.empty()) {
+        Entry.Function = "<unknown>";
+      } else {
+        Entry.Function = demangle(R.FunctionName);
+      }
       Entry.File = R.Loc ? R.Loc->SourceFilePath.str() : "";
       Entry.Line = R.Loc ? static_cast<int64_t>(R.Loc->SourceLine) : 0;
       Entry.Count = 0;
diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
index d930b55bb0bec..7f6004ba3244f 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalAnalyzer.cpp
@@ -2,6 +2,7 @@
 #include "Analysis/IR/RemarksRelationalAnalyzer.h"
 #include "Analysis/IR/RemarksRelationalSchema.h"
 #include "Analysis/RemarksAnalysisUtils.h"
+#include "llvm/Demangle/Demangle.h"
 
 using namespace llvm;
 using namespace llvm::advisor;
@@ -15,11 +16,13 @@ class RelationalBuilder {
     NameCol.push_back(static_cast<int64_t>(Name.getOrAdd(R.RemarkName)));
     TypeCol.push_back(static_cast<int64_t>(R.RemarkType));
 
-    if (R.FunctionName.empty())
+    if (R.FunctionName.empty()) {
       FunctionCol.push_back(-1);
-    else
+    } else {
+      std::string Demangled = demangle(R.FunctionName);
       FunctionCol.push_back(
-          static_cast<int64_t>(Function.getOrAdd(R.FunctionName)));
+          static_cast<int64_t>(Function.getOrAdd(Demangled)));
+    }
 
     if (R.Loc) {
       FileCol.push_back(

>From 900c20aaf0d1a9e19ba86914eee98442d49a668a Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 20 Jun 2026 22:01:47 +0530
Subject: [PATCH 21/41] [llvm-advisor] server-side filtering and pagination for
 remarks relational endpoint

The relational endpoint now accepts query parameters:
- pass, name, function, file: substring filters on string columns
- type: exact match on remark type enum
- min_hotness: minimum hotness threshold
- offset, limit: pagination (default limit 10000, max 100000)

Server scans all units, builds merged columns, applies filters,
then writes only the requested slice. Response includes total
(filtered count) for pagination.

Frontend triage grid is rewritten as server-paginated: fetches
one page at a time, filter inputs debounce 300ms then re-fetch
from server, page controls step through results.

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Analysis/IR/RemarksRelationalSchema.h |   6 +
 .../src/Client/HTTP/Assets/bundled.html       | 406 +++++-------------
 .../src/Client/HTTP/Assets/index_html.inc     | 406 +++++-------------
 .../src/Client/HTTP/Assets/overview.js        |   5 +-
 .../src/Client/HTTP/Assets/views.js           | 404 +++++------------
 .../src/Client/HTTP/HTTPServer.cpp            | 292 +++++++++++--
 6 files changed, 584 insertions(+), 935 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h
index 3c1e5fcf1b9da..8699be0aa2a3f 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h
+++ b/llvm/tools/llvm-advisor/src/Analysis/IR/RemarksRelationalSchema.h
@@ -22,6 +22,12 @@ class RelationalStringTable {
     return It->second;
   }
 
+  StringRef get(int64_t Idx) const {
+    if (Idx < 0 || static_cast<size_t>(Idx) >= Strings.size())
+      return "";
+    return Strings[static_cast<size_t>(Idx)];
+  }
+
   json::Array toJSON() const {
     json::Array Out;
     Out.reserve(Strings.size());
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index ac7fd8cea08eb..f1bb31f4a9a9b 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -2328,7 +2328,7 @@
 
     // Query core capabilities only — avoid expensive/unstable capabilities
     const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail',
+                      'llvm.obj.summary', 'llvm.remarks.summary',
                       'llvm.debug.summary', 'clang.ast.summary',
                       'llvm.lto.summary', 'llvm.lto.function_stats'];
     const registeredIds = new Set(specs.map(s => s.id));
@@ -4485,7 +4485,7 @@
     container.appendChild(skeleton);
 
     const [relRes, queryRes] = await Promise.all([
-      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.get(`/snapshots/${snap.id}/remarks/relational?limit=5000`),
       API.querySnapshot(snap.id, ['llvm.remarks.summary']),
     ]);
 
@@ -4517,8 +4517,9 @@
 
     // Header stat row
     const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
-    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
-    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    const actualTotal = (rel && rel.total) ? rel.total : totalRemarks;
+    statRow.appendChild(UI.metric('Total Remarks', actualTotal || totalRemarks));
+    statRow.appendChild(UI.metric('Units', snap.unit_count || queryUnits.length));
     if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
     container.appendChild(statRow);
 
@@ -4661,353 +4662,152 @@
         container.appendChild(tableSection);
       }
 
-      // Full triage grid: virtualised, filterable, sortable view of every
-      // remark in the relational payload. Lives below the summary tables.
-      container.appendChild(this._renderTriageGrid(rel));
+      // Full triage grid: server-paginated view of all remarks.
+      container.appendChild(this._renderTriageGrid(snap.id, totalRemarks));
     }
   },
 
-  // Triage Grid — Phase 1B of the proposal, against the C++ relational
-  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
-  // of ~32 row elements floats over an absolute-positioned spacer so that
-  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
-  // integer columns first; strings are dereferenced only for display.
-  _renderTriageGrid(rel) {
-    const { columns, strings } = rel;
-    const total = rel.count || 0;
-
-    // Canonical lowercase type keys; index = remarks::Type enum value.
-    const TYPE_NAMES = [
-      'unknown', 'passed', 'missed', 'analysis',
-      'analysis-fp-commute', 'analysis-aliasing', 'failure',
-    ];
-    const TYPE_LABELS = {
-      'unknown': 'Unknown',
-      'passed': 'Passed',
-      'missed': 'Missed',
-      'analysis': 'Analysis',
-      'analysis-fp-commute': 'FP-Commute',
-      'analysis-aliasing': 'Aliasing',
-      'failure': 'Failure',
-    };
-
-    // Column descriptors. `key` maps to a getter that resolves the integer
-    // column to a displayable value (string for text cells, number for
-    // numeric cells, null for missing).
-    const COLS = [
-      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
-        idx: (i) => columns.unit ? columns.unit[i] : -1 },
-      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => strings.pass[columns.pass[i]] || '?',
-        idx: (i) => columns.pass[i] },
-      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => strings.name[columns.name[i]] || '?',
-        idx: (i) => columns.name[i] },
-      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
-        idx: (i) => columns.type[i] },
-      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
-        idx: (i) => columns.function[i] },
-      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
-        get: (i) => {
-          const fi = columns.file[i];
-          if (fi < 0) return null;
-          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
-          return `${file}:${columns.line[i]}:${columns.column[i]}`;
-        } },
-      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
-        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
-        idx: (i) => columns.hotness[i] },
-    ];
+  _renderTriageGrid(snapshotId, totalRemarks) {
+    const PAGE_SIZE = 10000;
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4;
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+    const TYPE_LABELS = { unknown: 'Unknown', passed: 'Passed', missed: 'Missed', analysis: 'Analysis', 'analysis-fp-commute': 'FP-Commute', 'analysis-aliasing': 'Aliasing', failure: 'Failure' };
 
-    // Mutable state -------------------------------------------------------
-    let filtered = new Int32Array(total);
-    for (let i = 0; i < total; i++) filtered[i] = i;
-    let filteredLen = total;
-    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
-    let sortColId = null;
-    let sortDir = 1; // 1 = ascending, -1 = descending
+    let page = 0, pageCount = 0, serverTotal = 0;
+    let columns = {}, strings = {}, count = 0;
+    const filters = { pass: '', name: '', func: '', source: '', type: '' };
 
-    // DOM -----------------------------------------------------------------
     const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
-
-    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
-    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    const counter = h('span', { class: 'triage-counter' }, '...');
+    const pageInfo = h('span', { class: 'text-muted', style: { fontSize: '11px' } }, '');
     wrap.appendChild(h('div', { class: 'triage-header-row' },
       h('h3', { style: { margin: '0' } }, 'All Remarks'),
-      counter,
-      resetBtn,
+      counter, pageInfo
     ));
 
-    // Filter bar. Text inputs filter on a case-insensitive substring of the
-    // matching string column; type chips toggle a set of allowed type enum
-    // values; hotness slider filters on minimum hotness.
     const filterBar = h('div', { class: 'triage-filter-bar' });
-    const textFields = [
-      { key: 'pass',   placeholder: 'pass…' },
-      { key: 'name',   placeholder: 'remark name…' },
-      { key: 'func',   placeholder: 'function…' },
-      { key: 'source', placeholder: 'source file…' },
-    ];
-    textFields.forEach(f => {
-      const inp = h('input', {
-        class: 'triage-input',
-        type: 'search',
-        placeholder: f.placeholder,
-        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
-      });
+    const inputs = {};
+    [{ key: 'pass', placeholder: 'pass…' }, { key: 'name', placeholder: 'remark name…' }, { key: 'func', placeholder: 'function…' }, { key: 'source', placeholder: 'source file…' }].forEach(f => {
+      const inp = h('input', { class: 'triage-input', type: 'search', placeholder: f.placeholder });
+      inputs[f.key] = inp;
       filterBar.appendChild(inp);
     });
 
-    // Type chips — clickable on/off filters for each remarks::Type value.
     const typeChipBox = h('div', { class: 'triage-chips' });
     TYPE_NAMES.forEach((name, enumVal) => {
-      if (name === 'unknown') return; // hide unless they actually appear
-      const chip = h('button', {
-        class: `triage-chip triage-chip-${name}`,
-        title: `Toggle ${TYPE_LABELS[name]}`,
-        onClick: () => {
-          if (filters.types.has(enumVal)) {
-            filters.types.delete(enumVal);
-            chip.classList.remove('on');
-          } else {
-            filters.types.add(enumVal);
-            chip.classList.add('on');
-          }
-          refilter();
-        },
-      }, TYPE_LABELS[name]);
+      if (name === 'unknown') return;
+      const chip = h('button', { class: `triage-chip triage-chip-${name}` }, TYPE_LABELS[name]);
+      chip.addEventListener('click', () => {
+        if (filters.type === String(enumVal)) { filters.type = ''; chip.classList.remove('on'); }
+        else { filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on')); filters.type = String(enumVal); chip.classList.add('on'); }
+        page = 0; fetchPage();
+      });
       typeChipBox.appendChild(chip);
     });
     filterBar.appendChild(typeChipBox);
     wrap.appendChild(filterBar);
 
-    // Header row (sortable columns).
-    const tHead = h('div', { class: 'triage-thead' });
-    const thEls = {};
+    let debounce = null;
+    const onFilterInput = () => {
+      filters.pass = inputs.pass.value; filters.name = inputs.name.value;
+      filters.func = inputs.func.value; filters.source = inputs.source.value;
+      page = 0;
+      clearTimeout(debounce);
+      debounce = setTimeout(fetchPage, 300);
+    };
+    Object.values(inputs).forEach(inp => inp.addEventListener('input', onFilterInput));
+
+    const COLS = [
+      { id: 'unit', label: 'Unit', width: 80, mono: true },
+      { id: 'pass', label: 'Pass', width: 120, mono: true },
+      { id: 'name', label: 'Remark', width: 160 },
+      { id: 'type', label: 'Type', width: 80 },
+      { id: 'function', label: 'Function', width: 250, mono: true },
+      { id: 'source', label: 'Source', width: 200, mono: true },
+      { id: 'hotness', label: 'Hot', width: 60, align: 'right', mono: true },
+    ];
+
+    const colStyle = (col) => col.width ? { width: col.width + 'px', flexShrink: '0' } : { flex: col.flex, minWidth: '0' };
+
+    const tHead = h('div', { class: 'triage-thead', style: { display: 'flex' } });
     COLS.forEach(col => {
-      const th = h('div', {
-        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
-        style: { width: col.width + 'px' },
-        onClick: col.sortable ? () => onSort(col.id) : null,
-      },
-        h('span', { class: 'triage-th-label' }, col.label),
-        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
-      );
-      thEls[col.id] = th;
-      tHead.appendChild(th);
+      tHead.appendChild(h('div', { class: `triage-th${col.align === 'right' ? ' right' : ''}`, style: colStyle(col) }, col.label));
     });
     wrap.appendChild(tHead);
 
-    // Virtualised viewport.
-    const ROW_H = 26;
-    const VIEWPORT_ROWS = 22;
-    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
-
-    const viewport = h('div', {
-      class: 'triage-viewport',
-      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
-    });
+    const viewport = h('div', { class: 'triage-viewport', style: { height: `${VIEWPORT_ROWS * ROW_H}px` } });
     const spacer = h('div', { class: 'triage-spacer' });
-    spacer.style.height = `${total * ROW_H}px`;
     viewport.appendChild(spacer);
-
-    // Pre-allocate the row pool once. Each row is an absolutely-positioned
-    // flex container with one span per column. Scroll only mutates each
-    // span's textContent and the row's top position.
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row' });
-      row.style.height = `${ROW_H}px`;
-      const cells = COLS.map(col => h('span', {
-        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
-        style: { width: col.width + 'px' },
-      }, ''));
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
       pool.push({ row, cells });
     }
     wrap.appendChild(viewport);
 
-    // Empty-state element shown when filteredLen === 0.
-    const emptyEl = h('div', { class: 'triage-empty' },
-      'No remarks match the current filters.'
-    );
-    viewport.appendChild(emptyEl);
+    const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+    const prevBtn = h('button', { class: 'triage-chip', onClick: () => { if (page > 0) { page--; fetchPage(); } } }, '← Prev');
+    const nextBtn = h('button', { class: 'triage-chip', onClick: () => { if (page < pageCount - 1) { page++; fetchPage(); } } }, 'Next →');
+    const pageLabel = h('span', { class: 'text-muted' }, '');
+    pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+    wrap.appendChild(pager);
+
+    const getCell = (i, colId) => {
+      if (!columns.pass) return null;
+      switch (colId) {
+        case 'unit': return columns.unit ? (strings.unit?.[columns.unit[i]] || '').slice(0, 10) : '';
+        case 'pass': return strings.pass?.[columns.pass[i]] || '';
+        case 'name': return strings.name?.[columns.name[i]] || '';
+        case 'type': return TYPE_LABELS[TYPE_NAMES[columns.type[i]]] || '';
+        case 'function': return columns.function[i] < 0 ? '' : (strings.function?.[columns.function[i]] || '');
+        case 'source': { const fi = columns.file[i]; if (fi < 0) return ''; const f = (strings.file?.[fi] || '').split('/').pop(); return `${f}:${columns.line[i]}`; }
+        case 'hotness': return columns.hotness[i] < 0 ? '' : formatNumber(columns.hotness[i]);
+      }
+    };
 
-    // -----------------------------------------------------------------------
-    // Render the visible window. Called on scroll, filter, sort.
-    // -----------------------------------------------------------------------
     const renderVisible = () => {
-      const len = filteredLen;
-      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const len = count;
+      spacer.style.height = `${len * ROW_H}px`;
       const scrollTop = viewport.scrollTop;
       const first = Math.max(0, Math.floor(scrollTop / ROW_H));
       for (let p = 0; p < pool.length; p++) {
-        const visibleIdx = first + p;
+        const idx = first + p;
         const { row, cells } = pool[p];
-        if (visibleIdx >= len) {
-          row.style.display = 'none';
-          continue;
-        }
-        const r = filtered[visibleIdx];
-        row.style.display = '';
-        row.style.top = `${visibleIdx * ROW_H}px`;
-        for (let c = 0; c < COLS.length; c++) {
-          const col = COLS[c];
-          const cell = cells[c];
-          const val = col.get(r);
-          if (val === null || val === undefined) {
-            cell.textContent = '–';
-            cell.classList.add('triage-td-missing');
-          } else {
-            cell.classList.remove('triage-td-missing');
-            if (col.id === 'unit') {
-              cell.textContent = String(val).slice(0, 10);
-              cell.title = val;
-            } else if (col.id === 'type') {
-              cell.textContent = TYPE_LABELS[val] || val;
-              cell.className = `triage-td triage-type triage-type-${val}`;
-            } else if (col.num) {
-              cell.textContent = formatNumber(val);
-            } else {
-              cell.textContent = val;
-              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
-                cell.title = val;
-              }
-            }
-          }
-        }
-      }
-    };
-
-    // -----------------------------------------------------------------------
-    // Rebuild the filtered index array. O(N), runs on every filter change.
-    // -----------------------------------------------------------------------
-    const refilter = () => {
-      const out = new Int32Array(total);
-      let n = 0;
-      const fPass = filters.pass;
-      const fName = filters.name;
-      const fFunc = filters.func;
-      const fSource = filters.source;
-      const fTypes = filters.types;
-      const useTypes = fTypes.size > 0;
-
-      for (let i = 0; i < total; i++) {
-        if (useTypes && !fTypes.has(columns.type[i])) continue;
-        if (fPass) {
-          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
-          if (!s.includes(fPass)) continue;
-        }
-        if (fName) {
-          const s = (strings.name[columns.name[i]] || '').toLowerCase();
-          if (!s.includes(fName)) continue;
-        }
-        if (fFunc) {
-          const fi = columns.function[i];
-          if (fi < 0) continue;
-          const s = (strings.function[fi] || '').toLowerCase();
-          if (!s.includes(fFunc)) continue;
-        }
-        if (fSource) {
-          const fi = columns.file[i];
-          if (fi < 0) continue;
-          const s = (strings.file[fi] || '').toLowerCase();
-          if (!s.includes(fSource)) continue;
-        }
-        out[n++] = i;
-      }
-      filtered = out;
-      filteredLen = n;
-      spacer.style.height = `${n * ROW_H}px`;
-      viewport.scrollTop = 0;
-      counter.textContent = n === total
-        ? `${formatNumber(total)} remarks`
-        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
-      if (sortColId) applySort();
-      renderVisible();
-    };
-
-    // -----------------------------------------------------------------------
-    // Sort the filtered index array in place, then re-render.
-    // -----------------------------------------------------------------------
-    const applySort = () => {
-      const col = COLS.find(c => c.id === sortColId);
-      if (!col) return;
-      const dir = sortDir;
-      const view = Array.from(filtered.subarray(0, filteredLen));
-      if (col.idx) {
-        // Numeric / index sort, fast path. -1 sentinels sort last regardless
-        // of direction so missing values don't crowd the top.
-        view.sort((a, b) => {
-          const va = col.idx(a);
-          const vb = col.idx(b);
-          if (va < 0 && vb < 0) return 0;
-          if (va < 0) return 1;
-          if (vb < 0) return -1;
-          return (va - vb) * dir;
-        });
-      } else {
-        // Lexicographic fallback for text-only columns without an .idx.
-        view.sort((a, b) => {
-          const va = (col.get(a) || '').toString();
-          const vb = (col.get(b) || '').toString();
-          return va.localeCompare(vb) * dir;
-        });
+        if (idx >= len) { row.style.display = 'none'; continue; }
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
-      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
     };
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
 
-    const onSort = (colId) => {
-      if (sortColId === colId) {
-        sortDir = -sortDir;
-      } else {
-        sortColId = colId;
-        sortDir = 1;
-      }
-      applySort();
-      // Update sort indicators in the header.
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (!ind) return;
-        if (c.id === sortColId) {
-          ind.textContent = sortDir === 1 ? '▲' : '▼';
-          th.classList.add('sorted');
-        } else {
-          ind.textContent = '';
-          th.classList.remove('sorted');
-        }
-      });
+    const fetchPage = async () => {
+      const offset = page * PAGE_SIZE;
+      let url = `/snapshots/${encodeURIComponent(snapshotId)}/remarks/relational?offset=${offset}&limit=${PAGE_SIZE}`;
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.func) url += `&function=${encodeURIComponent(filters.func)}`;
+      if (filters.source) url += `&file=${encodeURIComponent(filters.source)}`;
+      if (filters.type) url += `&type=${filters.type}`;
+      counter.textContent = 'loading...';
+      const res = await API.get(url);
+      if (!res.ok) { counter.textContent = 'error'; return; }
+      const d = res.data;
+      columns = d.columns || {}; strings = d.strings || {};
+      count = d.count || 0; serverTotal = d.total || 0;
+      pageCount = Math.max(1, Math.ceil(serverTotal / PAGE_SIZE));
+      counter.textContent = `${formatNumber(serverTotal)} remarks`;
+      pageLabel.textContent = `Page ${page + 1} of ${formatNumber(pageCount)}`;
+      prevBtn.disabled = page === 0; nextBtn.disabled = page >= pageCount - 1;
       viewport.scrollTop = 0;
       renderVisible();
     };
 
-    const resetAll = () => {
-      filters.pass = filters.name = filters.func = filters.source = '';
-      filters.types.clear();
-      // Reset DOM
-      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
-      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
-      sortColId = null;
-      sortDir = 1;
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        th.classList.remove('sorted');
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (ind) ind.textContent = '';
-      });
-      refilter();
-    };
-
-    viewport.addEventListener('scroll', renderVisible, { passive: true });
-
-    // Initial render — defer until the viewport is laid out in the document.
-    requestAnimationFrame(renderVisible);
-
+    fetchPage();
     return wrap;
   },
 };
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 9c16c70411dd4..829e5568dad6d 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -2331,7 +2331,7 @@ const OverviewView = {
 
     // Query core capabilities only — avoid expensive/unstable capabilities
     const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail',
+                      'llvm.obj.summary', 'llvm.remarks.summary',
                       'llvm.debug.summary', 'clang.ast.summary',
                       'llvm.lto.summary', 'llvm.lto.function_stats'];
     const registeredIds = new Set(specs.map(s => s.id));
@@ -4488,7 +4488,7 @@ const RemarksView = {
     container.appendChild(skeleton);
 
     const [relRes, queryRes] = await Promise.all([
-      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.get(`/snapshots/${snap.id}/remarks/relational?limit=5000`),
       API.querySnapshot(snap.id, ['llvm.remarks.summary']),
     ]);
 
@@ -4520,8 +4520,9 @@ const RemarksView = {
 
     // Header stat row
     const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
-    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
-    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    const actualTotal = (rel && rel.total) ? rel.total : totalRemarks;
+    statRow.appendChild(UI.metric('Total Remarks', actualTotal || totalRemarks));
+    statRow.appendChild(UI.metric('Units', snap.unit_count || queryUnits.length));
     if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
     container.appendChild(statRow);
 
@@ -4664,353 +4665,152 @@ const RemarksView = {
         container.appendChild(tableSection);
       }
 
-      // Full triage grid: virtualised, filterable, sortable view of every
-      // remark in the relational payload. Lives below the summary tables.
-      container.appendChild(this._renderTriageGrid(rel));
+      // Full triage grid: server-paginated view of all remarks.
+      container.appendChild(this._renderTriageGrid(snap.id, totalRemarks));
     }
   },
 
-  // Triage Grid — Phase 1B of the proposal, against the C++ relational
-  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
-  // of ~32 row elements floats over an absolute-positioned spacer so that
-  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
-  // integer columns first; strings are dereferenced only for display.
-  _renderTriageGrid(rel) {
-    const { columns, strings } = rel;
-    const total = rel.count || 0;
-
-    // Canonical lowercase type keys; index = remarks::Type enum value.
-    const TYPE_NAMES = [
-      'unknown', 'passed', 'missed', 'analysis',
-      'analysis-fp-commute', 'analysis-aliasing', 'failure',
-    ];
-    const TYPE_LABELS = {
-      'unknown': 'Unknown',
-      'passed': 'Passed',
-      'missed': 'Missed',
-      'analysis': 'Analysis',
-      'analysis-fp-commute': 'FP-Commute',
-      'analysis-aliasing': 'Aliasing',
-      'failure': 'Failure',
-    };
-
-    // Column descriptors. `key` maps to a getter that resolves the integer
-    // column to a displayable value (string for text cells, number for
-    // numeric cells, null for missing).
-    const COLS = [
-      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
-        idx: (i) => columns.unit ? columns.unit[i] : -1 },
-      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => strings.pass[columns.pass[i]] || '?',
-        idx: (i) => columns.pass[i] },
-      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => strings.name[columns.name[i]] || '?',
-        idx: (i) => columns.name[i] },
-      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
-        idx: (i) => columns.type[i] },
-      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
-        idx: (i) => columns.function[i] },
-      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
-        get: (i) => {
-          const fi = columns.file[i];
-          if (fi < 0) return null;
-          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
-          return `${file}:${columns.line[i]}:${columns.column[i]}`;
-        } },
-      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
-        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
-        idx: (i) => columns.hotness[i] },
-    ];
+  _renderTriageGrid(snapshotId, totalRemarks) {
+    const PAGE_SIZE = 10000;
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4;
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+    const TYPE_LABELS = { unknown: 'Unknown', passed: 'Passed', missed: 'Missed', analysis: 'Analysis', 'analysis-fp-commute': 'FP-Commute', 'analysis-aliasing': 'Aliasing', failure: 'Failure' };
 
-    // Mutable state -------------------------------------------------------
-    let filtered = new Int32Array(total);
-    for (let i = 0; i < total; i++) filtered[i] = i;
-    let filteredLen = total;
-    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
-    let sortColId = null;
-    let sortDir = 1; // 1 = ascending, -1 = descending
+    let page = 0, pageCount = 0, serverTotal = 0;
+    let columns = {}, strings = {}, count = 0;
+    const filters = { pass: '', name: '', func: '', source: '', type: '' };
 
-    // DOM -----------------------------------------------------------------
     const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
-
-    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
-    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    const counter = h('span', { class: 'triage-counter' }, '...');
+    const pageInfo = h('span', { class: 'text-muted', style: { fontSize: '11px' } }, '');
     wrap.appendChild(h('div', { class: 'triage-header-row' },
       h('h3', { style: { margin: '0' } }, 'All Remarks'),
-      counter,
-      resetBtn,
+      counter, pageInfo
     ));
 
-    // Filter bar. Text inputs filter on a case-insensitive substring of the
-    // matching string column; type chips toggle a set of allowed type enum
-    // values; hotness slider filters on minimum hotness.
     const filterBar = h('div', { class: 'triage-filter-bar' });
-    const textFields = [
-      { key: 'pass',   placeholder: 'pass…' },
-      { key: 'name',   placeholder: 'remark name…' },
-      { key: 'func',   placeholder: 'function…' },
-      { key: 'source', placeholder: 'source file…' },
-    ];
-    textFields.forEach(f => {
-      const inp = h('input', {
-        class: 'triage-input',
-        type: 'search',
-        placeholder: f.placeholder,
-        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
-      });
+    const inputs = {};
+    [{ key: 'pass', placeholder: 'pass…' }, { key: 'name', placeholder: 'remark name…' }, { key: 'func', placeholder: 'function…' }, { key: 'source', placeholder: 'source file…' }].forEach(f => {
+      const inp = h('input', { class: 'triage-input', type: 'search', placeholder: f.placeholder });
+      inputs[f.key] = inp;
       filterBar.appendChild(inp);
     });
 
-    // Type chips — clickable on/off filters for each remarks::Type value.
     const typeChipBox = h('div', { class: 'triage-chips' });
     TYPE_NAMES.forEach((name, enumVal) => {
-      if (name === 'unknown') return; // hide unless they actually appear
-      const chip = h('button', {
-        class: `triage-chip triage-chip-${name}`,
-        title: `Toggle ${TYPE_LABELS[name]}`,
-        onClick: () => {
-          if (filters.types.has(enumVal)) {
-            filters.types.delete(enumVal);
-            chip.classList.remove('on');
-          } else {
-            filters.types.add(enumVal);
-            chip.classList.add('on');
-          }
-          refilter();
-        },
-      }, TYPE_LABELS[name]);
+      if (name === 'unknown') return;
+      const chip = h('button', { class: `triage-chip triage-chip-${name}` }, TYPE_LABELS[name]);
+      chip.addEventListener('click', () => {
+        if (filters.type === String(enumVal)) { filters.type = ''; chip.classList.remove('on'); }
+        else { filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on')); filters.type = String(enumVal); chip.classList.add('on'); }
+        page = 0; fetchPage();
+      });
       typeChipBox.appendChild(chip);
     });
     filterBar.appendChild(typeChipBox);
     wrap.appendChild(filterBar);
 
-    // Header row (sortable columns).
-    const tHead = h('div', { class: 'triage-thead' });
-    const thEls = {};
+    let debounce = null;
+    const onFilterInput = () => {
+      filters.pass = inputs.pass.value; filters.name = inputs.name.value;
+      filters.func = inputs.func.value; filters.source = inputs.source.value;
+      page = 0;
+      clearTimeout(debounce);
+      debounce = setTimeout(fetchPage, 300);
+    };
+    Object.values(inputs).forEach(inp => inp.addEventListener('input', onFilterInput));
+
+    const COLS = [
+      { id: 'unit', label: 'Unit', width: 80, mono: true },
+      { id: 'pass', label: 'Pass', width: 120, mono: true },
+      { id: 'name', label: 'Remark', width: 160 },
+      { id: 'type', label: 'Type', width: 80 },
+      { id: 'function', label: 'Function', width: 250, mono: true },
+      { id: 'source', label: 'Source', width: 200, mono: true },
+      { id: 'hotness', label: 'Hot', width: 60, align: 'right', mono: true },
+    ];
+
+    const colStyle = (col) => col.width ? { width: col.width + 'px', flexShrink: '0' } : { flex: col.flex, minWidth: '0' };
+
+    const tHead = h('div', { class: 'triage-thead', style: { display: 'flex' } });
     COLS.forEach(col => {
-      const th = h('div', {
-        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
-        style: { width: col.width + 'px' },
-        onClick: col.sortable ? () => onSort(col.id) : null,
-      },
-        h('span', { class: 'triage-th-label' }, col.label),
-        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
-      );
-      thEls[col.id] = th;
-      tHead.appendChild(th);
+      tHead.appendChild(h('div', { class: `triage-th${col.align === 'right' ? ' right' : ''}`, style: colStyle(col) }, col.label));
     });
     wrap.appendChild(tHead);
 
-    // Virtualised viewport.
-    const ROW_H = 26;
-    const VIEWPORT_ROWS = 22;
-    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
-
-    const viewport = h('div', {
-      class: 'triage-viewport',
-      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
-    });
+    const viewport = h('div', { class: 'triage-viewport', style: { height: `${VIEWPORT_ROWS * ROW_H}px` } });
     const spacer = h('div', { class: 'triage-spacer' });
-    spacer.style.height = `${total * ROW_H}px`;
     viewport.appendChild(spacer);
-
-    // Pre-allocate the row pool once. Each row is an absolutely-positioned
-    // flex container with one span per column. Scroll only mutates each
-    // span's textContent and the row's top position.
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row' });
-      row.style.height = `${ROW_H}px`;
-      const cells = COLS.map(col => h('span', {
-        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
-        style: { width: col.width + 'px' },
-      }, ''));
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
       pool.push({ row, cells });
     }
     wrap.appendChild(viewport);
 
-    // Empty-state element shown when filteredLen === 0.
-    const emptyEl = h('div', { class: 'triage-empty' },
-      'No remarks match the current filters.'
-    );
-    viewport.appendChild(emptyEl);
+    const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+    const prevBtn = h('button', { class: 'triage-chip', onClick: () => { if (page > 0) { page--; fetchPage(); } } }, '← Prev');
+    const nextBtn = h('button', { class: 'triage-chip', onClick: () => { if (page < pageCount - 1) { page++; fetchPage(); } } }, 'Next →');
+    const pageLabel = h('span', { class: 'text-muted' }, '');
+    pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+    wrap.appendChild(pager);
+
+    const getCell = (i, colId) => {
+      if (!columns.pass) return null;
+      switch (colId) {
+        case 'unit': return columns.unit ? (strings.unit?.[columns.unit[i]] || '').slice(0, 10) : '';
+        case 'pass': return strings.pass?.[columns.pass[i]] || '';
+        case 'name': return strings.name?.[columns.name[i]] || '';
+        case 'type': return TYPE_LABELS[TYPE_NAMES[columns.type[i]]] || '';
+        case 'function': return columns.function[i] < 0 ? '' : (strings.function?.[columns.function[i]] || '');
+        case 'source': { const fi = columns.file[i]; if (fi < 0) return ''; const f = (strings.file?.[fi] || '').split('/').pop(); return `${f}:${columns.line[i]}`; }
+        case 'hotness': return columns.hotness[i] < 0 ? '' : formatNumber(columns.hotness[i]);
+      }
+    };
 
-    // -----------------------------------------------------------------------
-    // Render the visible window. Called on scroll, filter, sort.
-    // -----------------------------------------------------------------------
     const renderVisible = () => {
-      const len = filteredLen;
-      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const len = count;
+      spacer.style.height = `${len * ROW_H}px`;
       const scrollTop = viewport.scrollTop;
       const first = Math.max(0, Math.floor(scrollTop / ROW_H));
       for (let p = 0; p < pool.length; p++) {
-        const visibleIdx = first + p;
+        const idx = first + p;
         const { row, cells } = pool[p];
-        if (visibleIdx >= len) {
-          row.style.display = 'none';
-          continue;
-        }
-        const r = filtered[visibleIdx];
-        row.style.display = '';
-        row.style.top = `${visibleIdx * ROW_H}px`;
-        for (let c = 0; c < COLS.length; c++) {
-          const col = COLS[c];
-          const cell = cells[c];
-          const val = col.get(r);
-          if (val === null || val === undefined) {
-            cell.textContent = '–';
-            cell.classList.add('triage-td-missing');
-          } else {
-            cell.classList.remove('triage-td-missing');
-            if (col.id === 'unit') {
-              cell.textContent = String(val).slice(0, 10);
-              cell.title = val;
-            } else if (col.id === 'type') {
-              cell.textContent = TYPE_LABELS[val] || val;
-              cell.className = `triage-td triage-type triage-type-${val}`;
-            } else if (col.num) {
-              cell.textContent = formatNumber(val);
-            } else {
-              cell.textContent = val;
-              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
-                cell.title = val;
-              }
-            }
-          }
-        }
-      }
-    };
-
-    // -----------------------------------------------------------------------
-    // Rebuild the filtered index array. O(N), runs on every filter change.
-    // -----------------------------------------------------------------------
-    const refilter = () => {
-      const out = new Int32Array(total);
-      let n = 0;
-      const fPass = filters.pass;
-      const fName = filters.name;
-      const fFunc = filters.func;
-      const fSource = filters.source;
-      const fTypes = filters.types;
-      const useTypes = fTypes.size > 0;
-
-      for (let i = 0; i < total; i++) {
-        if (useTypes && !fTypes.has(columns.type[i])) continue;
-        if (fPass) {
-          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
-          if (!s.includes(fPass)) continue;
-        }
-        if (fName) {
-          const s = (strings.name[columns.name[i]] || '').toLowerCase();
-          if (!s.includes(fName)) continue;
-        }
-        if (fFunc) {
-          const fi = columns.function[i];
-          if (fi < 0) continue;
-          const s = (strings.function[fi] || '').toLowerCase();
-          if (!s.includes(fFunc)) continue;
-        }
-        if (fSource) {
-          const fi = columns.file[i];
-          if (fi < 0) continue;
-          const s = (strings.file[fi] || '').toLowerCase();
-          if (!s.includes(fSource)) continue;
-        }
-        out[n++] = i;
-      }
-      filtered = out;
-      filteredLen = n;
-      spacer.style.height = `${n * ROW_H}px`;
-      viewport.scrollTop = 0;
-      counter.textContent = n === total
-        ? `${formatNumber(total)} remarks`
-        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
-      if (sortColId) applySort();
-      renderVisible();
-    };
-
-    // -----------------------------------------------------------------------
-    // Sort the filtered index array in place, then re-render.
-    // -----------------------------------------------------------------------
-    const applySort = () => {
-      const col = COLS.find(c => c.id === sortColId);
-      if (!col) return;
-      const dir = sortDir;
-      const view = Array.from(filtered.subarray(0, filteredLen));
-      if (col.idx) {
-        // Numeric / index sort, fast path. -1 sentinels sort last regardless
-        // of direction so missing values don't crowd the top.
-        view.sort((a, b) => {
-          const va = col.idx(a);
-          const vb = col.idx(b);
-          if (va < 0 && vb < 0) return 0;
-          if (va < 0) return 1;
-          if (vb < 0) return -1;
-          return (va - vb) * dir;
-        });
-      } else {
-        // Lexicographic fallback for text-only columns without an .idx.
-        view.sort((a, b) => {
-          const va = (col.get(a) || '').toString();
-          const vb = (col.get(b) || '').toString();
-          return va.localeCompare(vb) * dir;
-        });
+        if (idx >= len) { row.style.display = 'none'; continue; }
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
-      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
     };
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
 
-    const onSort = (colId) => {
-      if (sortColId === colId) {
-        sortDir = -sortDir;
-      } else {
-        sortColId = colId;
-        sortDir = 1;
-      }
-      applySort();
-      // Update sort indicators in the header.
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (!ind) return;
-        if (c.id === sortColId) {
-          ind.textContent = sortDir === 1 ? '▲' : '▼';
-          th.classList.add('sorted');
-        } else {
-          ind.textContent = '';
-          th.classList.remove('sorted');
-        }
-      });
+    const fetchPage = async () => {
+      const offset = page * PAGE_SIZE;
+      let url = `/snapshots/${encodeURIComponent(snapshotId)}/remarks/relational?offset=${offset}&limit=${PAGE_SIZE}`;
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.func) url += `&function=${encodeURIComponent(filters.func)}`;
+      if (filters.source) url += `&file=${encodeURIComponent(filters.source)}`;
+      if (filters.type) url += `&type=${filters.type}`;
+      counter.textContent = 'loading...';
+      const res = await API.get(url);
+      if (!res.ok) { counter.textContent = 'error'; return; }
+      const d = res.data;
+      columns = d.columns || {}; strings = d.strings || {};
+      count = d.count || 0; serverTotal = d.total || 0;
+      pageCount = Math.max(1, Math.ceil(serverTotal / PAGE_SIZE));
+      counter.textContent = `${formatNumber(serverTotal)} remarks`;
+      pageLabel.textContent = `Page ${page + 1} of ${formatNumber(pageCount)}`;
+      prevBtn.disabled = page === 0; nextBtn.disabled = page >= pageCount - 1;
       viewport.scrollTop = 0;
       renderVisible();
     };
 
-    const resetAll = () => {
-      filters.pass = filters.name = filters.func = filters.source = '';
-      filters.types.clear();
-      // Reset DOM
-      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
-      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
-      sortColId = null;
-      sortDir = 1;
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        th.classList.remove('sorted');
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (ind) ind.textContent = '';
-      });
-      refilter();
-    };
-
-    viewport.addEventListener('scroll', renderVisible, { passive: true });
-
-    // Initial render — defer until the viewport is laid out in the document.
-    requestAnimationFrame(renderVisible);
-
+    fetchPage();
     return wrap;
   },
 };
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
index a52d95d0679ad..ba7c08107599e 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
@@ -72,7 +72,10 @@ const OverviewView = {
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
+    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
+                      'llvm.obj.summary', 'llvm.remarks.summary',
+                      'llvm.debug.summary', 'clang.ast.summary',
+                      'llvm.lto.summary', 'llvm.lto.function_stats'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 5045b0b2ce8c8..8d0def52ccc31 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -731,7 +731,7 @@ const RemarksView = {
     container.appendChild(skeleton);
 
     const [relRes, queryRes] = await Promise.all([
-      API.get(`/snapshots/${snap.id}/remarks/relational`),
+      API.get(`/snapshots/${snap.id}/remarks/relational?limit=5000`),
       API.querySnapshot(snap.id, ['llvm.remarks.summary']),
     ]);
 
@@ -763,8 +763,9 @@ const RemarksView = {
 
     // Header stat row
     const statRow = h('div', { class: 'metric-cards', style: { marginBottom: '18px' } });
-    statRow.appendChild(UI.metric('Total Remarks', totalRemarks));
-    statRow.appendChild(UI.metric('Units', queryUnits.length));
+    const actualTotal = (rel && rel.total) ? rel.total : totalRemarks;
+    statRow.appendChild(UI.metric('Total Remarks', actualTotal || totalRemarks));
+    statRow.appendChild(UI.metric('Units', snap.unit_count || queryUnits.length));
     if (rel) statRow.appendChild(UI.metric('Relational Rows', rel.count || 0));
     container.appendChild(statRow);
 
@@ -907,353 +908,152 @@ const RemarksView = {
         container.appendChild(tableSection);
       }
 
-      // Full triage grid: virtualised, filterable, sortable view of every
-      // remark in the relational payload. Lives below the summary tables.
-      container.appendChild(this._renderTriageGrid(rel));
+      // Full triage grid: server-paginated view of all remarks.
+      container.appendChild(this._renderTriageGrid(snap.id, totalRemarks));
     }
   },
 
-  // Triage Grid — Phase 1B of the proposal, against the C++ relational
-  // endpoint. Renders one row per remark via DOM virtualisation: a fixed pool
-  // of ~32 row elements floats over an absolute-positioned spacer so that
-  // arbitrarily large payloads stay smooth. Filters and sorts operate on the
-  // integer columns first; strings are dereferenced only for display.
-  _renderTriageGrid(rel) {
-    const { columns, strings } = rel;
-    const total = rel.count || 0;
-
-    // Canonical lowercase type keys; index = remarks::Type enum value.
-    const TYPE_NAMES = [
-      'unknown', 'passed', 'missed', 'analysis',
-      'analysis-fp-commute', 'analysis-aliasing', 'failure',
-    ];
-    const TYPE_LABELS = {
-      'unknown': 'Unknown',
-      'passed': 'Passed',
-      'missed': 'Missed',
-      'analysis': 'Analysis',
-      'analysis-fp-commute': 'FP-Commute',
-      'analysis-aliasing': 'Aliasing',
-      'failure': 'Failure',
-    };
-
-    // Column descriptors. `key` maps to a getter that resolves the integer
-    // column to a displayable value (string for text cells, number for
-    // numeric cells, null for missing).
-    const COLS = [
-      { id: 'unit',     label: 'Unit',     width: 90,  sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.unit ? (strings.unit?.[columns.unit[i]] || null) : null,
-        idx: (i) => columns.unit ? columns.unit[i] : -1 },
-      { id: 'pass',     label: 'Pass',     width: 160, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => strings.pass[columns.pass[i]] || '?',
-        idx: (i) => columns.pass[i] },
-      { id: 'name',     label: 'Remark',   width: 200, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => strings.name[columns.name[i]] || '?',
-        idx: (i) => columns.name[i] },
-      { id: 'type',     label: 'Type',     width: 100, sortable: true,  align: 'left',  mono: false, text: true,
-        get: (i) => TYPE_NAMES[columns.type[i]] || 'unknown',
-        idx: (i) => columns.type[i] },
-      { id: 'function', label: 'Function', width: 200, sortable: true,  align: 'left',  mono: true,  text: true,
-        get: (i) => columns.function[i] < 0 ? null : (strings.function[columns.function[i]] || '?'),
-        idx: (i) => columns.function[i] },
-      { id: 'source',   label: 'Source',   width: 220, sortable: false, align: 'left',  mono: true,  text: true,
-        get: (i) => {
-          const fi = columns.file[i];
-          if (fi < 0) return null;
-          const file = (strings.file[fi] || '?').split('/').pop() || strings.file[fi];
-          return `${file}:${columns.line[i]}:${columns.column[i]}`;
-        } },
-      { id: 'hotness',  label: 'Hot',      width: 80,  sortable: true,  align: 'right', mono: true,  num: true,
-        get: (i) => columns.hotness[i] < 0 ? null : columns.hotness[i],
-        idx: (i) => columns.hotness[i] },
-    ];
+  _renderTriageGrid(snapshotId, totalRemarks) {
+    const PAGE_SIZE = 10000;
+    const ROW_H = 26;
+    const VIEWPORT_ROWS = 22;
+    const POOL_SIZE = VIEWPORT_ROWS + 4;
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'analysis-fp-commute', 'analysis-aliasing', 'failure'];
+    const TYPE_LABELS = { unknown: 'Unknown', passed: 'Passed', missed: 'Missed', analysis: 'Analysis', 'analysis-fp-commute': 'FP-Commute', 'analysis-aliasing': 'Aliasing', failure: 'Failure' };
 
-    // Mutable state -------------------------------------------------------
-    let filtered = new Int32Array(total);
-    for (let i = 0; i < total; i++) filtered[i] = i;
-    let filteredLen = total;
-    const filters = { pass: '', name: '', func: '', source: '', types: new Set() };
-    let sortColId = null;
-    let sortDir = 1; // 1 = ascending, -1 = descending
+    let page = 0, pageCount = 0, serverTotal = 0;
+    let columns = {}, strings = {}, count = 0;
+    const filters = { pass: '', name: '', func: '', source: '', type: '' };
 
-    // DOM -----------------------------------------------------------------
     const wrap = h('div', { class: 'chart-section triage-grid', style: { marginTop: '18px' } });
-
-    const counter = h('span', { class: 'triage-counter' }, `${formatNumber(total)} remarks`);
-    const resetBtn = h('button', { class: 'triage-reset', onClick: () => resetAll() }, 'Reset');
+    const counter = h('span', { class: 'triage-counter' }, '...');
+    const pageInfo = h('span', { class: 'text-muted', style: { fontSize: '11px' } }, '');
     wrap.appendChild(h('div', { class: 'triage-header-row' },
       h('h3', { style: { margin: '0' } }, 'All Remarks'),
-      counter,
-      resetBtn,
+      counter, pageInfo
     ));
 
-    // Filter bar. Text inputs filter on a case-insensitive substring of the
-    // matching string column; type chips toggle a set of allowed type enum
-    // values; hotness slider filters on minimum hotness.
     const filterBar = h('div', { class: 'triage-filter-bar' });
-    const textFields = [
-      { key: 'pass',   placeholder: 'pass…' },
-      { key: 'name',   placeholder: 'remark name…' },
-      { key: 'func',   placeholder: 'function…' },
-      { key: 'source', placeholder: 'source file…' },
-    ];
-    textFields.forEach(f => {
-      const inp = h('input', {
-        class: 'triage-input',
-        type: 'search',
-        placeholder: f.placeholder,
-        onInput: (e) => { filters[f.key] = e.target.value.toLowerCase(); refilter(); },
-      });
+    const inputs = {};
+    [{ key: 'pass', placeholder: 'pass…' }, { key: 'name', placeholder: 'remark name…' }, { key: 'func', placeholder: 'function…' }, { key: 'source', placeholder: 'source file…' }].forEach(f => {
+      const inp = h('input', { class: 'triage-input', type: 'search', placeholder: f.placeholder });
+      inputs[f.key] = inp;
       filterBar.appendChild(inp);
     });
 
-    // Type chips — clickable on/off filters for each remarks::Type value.
     const typeChipBox = h('div', { class: 'triage-chips' });
     TYPE_NAMES.forEach((name, enumVal) => {
-      if (name === 'unknown') return; // hide unless they actually appear
-      const chip = h('button', {
-        class: `triage-chip triage-chip-${name}`,
-        title: `Toggle ${TYPE_LABELS[name]}`,
-        onClick: () => {
-          if (filters.types.has(enumVal)) {
-            filters.types.delete(enumVal);
-            chip.classList.remove('on');
-          } else {
-            filters.types.add(enumVal);
-            chip.classList.add('on');
-          }
-          refilter();
-        },
-      }, TYPE_LABELS[name]);
+      if (name === 'unknown') return;
+      const chip = h('button', { class: `triage-chip triage-chip-${name}` }, TYPE_LABELS[name]);
+      chip.addEventListener('click', () => {
+        if (filters.type === String(enumVal)) { filters.type = ''; chip.classList.remove('on'); }
+        else { filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on')); filters.type = String(enumVal); chip.classList.add('on'); }
+        page = 0; fetchPage();
+      });
       typeChipBox.appendChild(chip);
     });
     filterBar.appendChild(typeChipBox);
     wrap.appendChild(filterBar);
 
-    // Header row (sortable columns).
-    const tHead = h('div', { class: 'triage-thead' });
-    const thEls = {};
+    let debounce = null;
+    const onFilterInput = () => {
+      filters.pass = inputs.pass.value; filters.name = inputs.name.value;
+      filters.func = inputs.func.value; filters.source = inputs.source.value;
+      page = 0;
+      clearTimeout(debounce);
+      debounce = setTimeout(fetchPage, 300);
+    };
+    Object.values(inputs).forEach(inp => inp.addEventListener('input', onFilterInput));
+
+    const COLS = [
+      { id: 'unit', label: 'Unit', width: 80, mono: true },
+      { id: 'pass', label: 'Pass', width: 120, mono: true },
+      { id: 'name', label: 'Remark', width: 160 },
+      { id: 'type', label: 'Type', width: 80 },
+      { id: 'function', label: 'Function', width: 250, mono: true },
+      { id: 'source', label: 'Source', width: 200, mono: true },
+      { id: 'hotness', label: 'Hot', width: 60, align: 'right', mono: true },
+    ];
+
+    const colStyle = (col) => col.width ? { width: col.width + 'px', flexShrink: '0' } : { flex: col.flex, minWidth: '0' };
+
+    const tHead = h('div', { class: 'triage-thead', style: { display: 'flex' } });
     COLS.forEach(col => {
-      const th = h('div', {
-        class: `triage-th${col.align === 'right' ? ' right' : ''}${col.sortable ? ' sortable' : ''}`,
-        style: { width: col.width + 'px' },
-        onClick: col.sortable ? () => onSort(col.id) : null,
-      },
-        h('span', { class: 'triage-th-label' }, col.label),
-        col.sortable ? h('span', { class: 'triage-sort-indicator' }, '') : null,
-      );
-      thEls[col.id] = th;
-      tHead.appendChild(th);
+      tHead.appendChild(h('div', { class: `triage-th${col.align === 'right' ? ' right' : ''}`, style: colStyle(col) }, col.label));
     });
     wrap.appendChild(tHead);
 
-    // Virtualised viewport.
-    const ROW_H = 26;
-    const VIEWPORT_ROWS = 22;
-    const POOL_SIZE = VIEWPORT_ROWS + 4; // a couple extra for smoother scroll
-
-    const viewport = h('div', {
-      class: 'triage-viewport',
-      style: { height: `${VIEWPORT_ROWS * ROW_H}px` },
-    });
+    const viewport = h('div', { class: 'triage-viewport', style: { height: `${VIEWPORT_ROWS * ROW_H}px` } });
     const spacer = h('div', { class: 'triage-spacer' });
-    spacer.style.height = `${total * ROW_H}px`;
     viewport.appendChild(spacer);
-
-    // Pre-allocate the row pool once. Each row is an absolutely-positioned
-    // flex container with one span per column. Scroll only mutates each
-    // span's textContent and the row's top position.
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row' });
-      row.style.height = `${ROW_H}px`;
-      const cells = COLS.map(col => h('span', {
-        class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}${col.num ? ' num' : ''}`,
-        style: { width: col.width + 'px' },
-      }, ''));
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
       pool.push({ row, cells });
     }
     wrap.appendChild(viewport);
 
-    // Empty-state element shown when filteredLen === 0.
-    const emptyEl = h('div', { class: 'triage-empty' },
-      'No remarks match the current filters.'
-    );
-    viewport.appendChild(emptyEl);
+    const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+    const prevBtn = h('button', { class: 'triage-chip', onClick: () => { if (page > 0) { page--; fetchPage(); } } }, '← Prev');
+    const nextBtn = h('button', { class: 'triage-chip', onClick: () => { if (page < pageCount - 1) { page++; fetchPage(); } } }, 'Next →');
+    const pageLabel = h('span', { class: 'text-muted' }, '');
+    pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+    wrap.appendChild(pager);
+
+    const getCell = (i, colId) => {
+      if (!columns.pass) return null;
+      switch (colId) {
+        case 'unit': return columns.unit ? (strings.unit?.[columns.unit[i]] || '').slice(0, 10) : '';
+        case 'pass': return strings.pass?.[columns.pass[i]] || '';
+        case 'name': return strings.name?.[columns.name[i]] || '';
+        case 'type': return TYPE_LABELS[TYPE_NAMES[columns.type[i]]] || '';
+        case 'function': return columns.function[i] < 0 ? '' : (strings.function?.[columns.function[i]] || '');
+        case 'source': { const fi = columns.file[i]; if (fi < 0) return ''; const f = (strings.file?.[fi] || '').split('/').pop(); return `${f}:${columns.line[i]}`; }
+        case 'hotness': return columns.hotness[i] < 0 ? '' : formatNumber(columns.hotness[i]);
+      }
+    };
 
-    // -----------------------------------------------------------------------
-    // Render the visible window. Called on scroll, filter, sort.
-    // -----------------------------------------------------------------------
     const renderVisible = () => {
-      const len = filteredLen;
-      emptyEl.style.display = len === 0 ? 'flex' : 'none';
+      const len = count;
+      spacer.style.height = `${len * ROW_H}px`;
       const scrollTop = viewport.scrollTop;
       const first = Math.max(0, Math.floor(scrollTop / ROW_H));
       for (let p = 0; p < pool.length; p++) {
-        const visibleIdx = first + p;
+        const idx = first + p;
         const { row, cells } = pool[p];
-        if (visibleIdx >= len) {
-          row.style.display = 'none';
-          continue;
-        }
-        const r = filtered[visibleIdx];
-        row.style.display = '';
-        row.style.top = `${visibleIdx * ROW_H}px`;
-        for (let c = 0; c < COLS.length; c++) {
-          const col = COLS[c];
-          const cell = cells[c];
-          const val = col.get(r);
-          if (val === null || val === undefined) {
-            cell.textContent = '–';
-            cell.classList.add('triage-td-missing');
-          } else {
-            cell.classList.remove('triage-td-missing');
-            if (col.id === 'unit') {
-              cell.textContent = String(val).slice(0, 10);
-              cell.title = val;
-            } else if (col.id === 'type') {
-              cell.textContent = TYPE_LABELS[val] || val;
-              cell.className = `triage-td triage-type triage-type-${val}`;
-            } else if (col.num) {
-              cell.textContent = formatNumber(val);
-            } else {
-              cell.textContent = val;
-              if (col.id === 'source' || col.id === 'function' || col.id === 'name') {
-                cell.title = val;
-              }
-            }
-          }
-        }
-      }
-    };
-
-    // -----------------------------------------------------------------------
-    // Rebuild the filtered index array. O(N), runs on every filter change.
-    // -----------------------------------------------------------------------
-    const refilter = () => {
-      const out = new Int32Array(total);
-      let n = 0;
-      const fPass = filters.pass;
-      const fName = filters.name;
-      const fFunc = filters.func;
-      const fSource = filters.source;
-      const fTypes = filters.types;
-      const useTypes = fTypes.size > 0;
-
-      for (let i = 0; i < total; i++) {
-        if (useTypes && !fTypes.has(columns.type[i])) continue;
-        if (fPass) {
-          const s = (strings.pass[columns.pass[i]] || '').toLowerCase();
-          if (!s.includes(fPass)) continue;
-        }
-        if (fName) {
-          const s = (strings.name[columns.name[i]] || '').toLowerCase();
-          if (!s.includes(fName)) continue;
-        }
-        if (fFunc) {
-          const fi = columns.function[i];
-          if (fi < 0) continue;
-          const s = (strings.function[fi] || '').toLowerCase();
-          if (!s.includes(fFunc)) continue;
-        }
-        if (fSource) {
-          const fi = columns.file[i];
-          if (fi < 0) continue;
-          const s = (strings.file[fi] || '').toLowerCase();
-          if (!s.includes(fSource)) continue;
-        }
-        out[n++] = i;
-      }
-      filtered = out;
-      filteredLen = n;
-      spacer.style.height = `${n * ROW_H}px`;
-      viewport.scrollTop = 0;
-      counter.textContent = n === total
-        ? `${formatNumber(total)} remarks`
-        : `${formatNumber(n)} of ${formatNumber(total)} remarks`;
-      if (sortColId) applySort();
-      renderVisible();
-    };
-
-    // -----------------------------------------------------------------------
-    // Sort the filtered index array in place, then re-render.
-    // -----------------------------------------------------------------------
-    const applySort = () => {
-      const col = COLS.find(c => c.id === sortColId);
-      if (!col) return;
-      const dir = sortDir;
-      const view = Array.from(filtered.subarray(0, filteredLen));
-      if (col.idx) {
-        // Numeric / index sort, fast path. -1 sentinels sort last regardless
-        // of direction so missing values don't crowd the top.
-        view.sort((a, b) => {
-          const va = col.idx(a);
-          const vb = col.idx(b);
-          if (va < 0 && vb < 0) return 0;
-          if (va < 0) return 1;
-          if (vb < 0) return -1;
-          return (va - vb) * dir;
-        });
-      } else {
-        // Lexicographic fallback for text-only columns without an .idx.
-        view.sort((a, b) => {
-          const va = (col.get(a) || '').toString();
-          const vb = (col.get(b) || '').toString();
-          return va.localeCompare(vb) * dir;
-        });
+        if (idx >= len) { row.style.display = 'none'; continue; }
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
-      for (let i = 0; i < filteredLen; i++) filtered[i] = view[i];
     };
+    viewport.addEventListener('scroll', renderVisible, { passive: true });
 
-    const onSort = (colId) => {
-      if (sortColId === colId) {
-        sortDir = -sortDir;
-      } else {
-        sortColId = colId;
-        sortDir = 1;
-      }
-      applySort();
-      // Update sort indicators in the header.
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (!ind) return;
-        if (c.id === sortColId) {
-          ind.textContent = sortDir === 1 ? '▲' : '▼';
-          th.classList.add('sorted');
-        } else {
-          ind.textContent = '';
-          th.classList.remove('sorted');
-        }
-      });
+    const fetchPage = async () => {
+      const offset = page * PAGE_SIZE;
+      let url = `/snapshots/${encodeURIComponent(snapshotId)}/remarks/relational?offset=${offset}&limit=${PAGE_SIZE}`;
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.func) url += `&function=${encodeURIComponent(filters.func)}`;
+      if (filters.source) url += `&file=${encodeURIComponent(filters.source)}`;
+      if (filters.type) url += `&type=${filters.type}`;
+      counter.textContent = 'loading...';
+      const res = await API.get(url);
+      if (!res.ok) { counter.textContent = 'error'; return; }
+      const d = res.data;
+      columns = d.columns || {}; strings = d.strings || {};
+      count = d.count || 0; serverTotal = d.total || 0;
+      pageCount = Math.max(1, Math.ceil(serverTotal / PAGE_SIZE));
+      counter.textContent = `${formatNumber(serverTotal)} remarks`;
+      pageLabel.textContent = `Page ${page + 1} of ${formatNumber(pageCount)}`;
+      prevBtn.disabled = page === 0; nextBtn.disabled = page >= pageCount - 1;
       viewport.scrollTop = 0;
       renderVisible();
     };
 
-    const resetAll = () => {
-      filters.pass = filters.name = filters.func = filters.source = '';
-      filters.types.clear();
-      // Reset DOM
-      filterBar.querySelectorAll('input.triage-input').forEach(i => { i.value = ''; });
-      filterBar.querySelectorAll('.triage-chip.on').forEach(c => c.classList.remove('on'));
-      sortColId = null;
-      sortDir = 1;
-      COLS.forEach(c => {
-        const th = thEls[c.id];
-        th.classList.remove('sorted');
-        const ind = th.querySelector('.triage-sort-indicator');
-        if (ind) ind.textContent = '';
-      });
-      refilter();
-    };
-
-    viewport.addEventListener('scroll', renderVisible, { passive: true });
-
-    // Initial render — defer until the viewport is laid out in the document.
-    requestAnimationFrame(renderVisible);
-
+    fetchPage();
     return wrap;
   },
 };
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 8022a90634508..3da1334d0556a 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -19,6 +19,7 @@
 #include <cerrno>
 #include <cstring>
 #include <cmath>
+#include <mutex>
 #include <string>
 #include <thread>
 
@@ -33,6 +34,8 @@
 using namespace llvm;
 using namespace llvm::advisor;
 
+static std::mutex HeavyQueryMutex;
+
 static std::string renderJSON(const json::Value &Value) {
   std::string Body;
   raw_string_ostream OS(Body);
@@ -398,6 +401,7 @@ static bool isSummarySafeCapability(StringRef ID) {
 }
 
 static HTTPResult handleGetSummary(CoreClient &Client, StringRef SnapID) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
   json::Object Summary;
   Summary["snapshot_id"] = SnapID;
   auto Units = Client.listUnits(SnapID);
@@ -578,6 +582,12 @@ class RelationalMerger {
     JOS.objectEnd();
   }
 
+  size_t size() const { return UnitColG.size(); }
+
+  RelationalStringTable Unit, Pass, Name, Function, File;
+  std::vector<int64_t> UnitColG, PassColG, NameColG, TypeColG, FuncColG,
+      FileColG, LineColG, ColumnColG, HotnessColG;
+
 private:
 
   static std::vector<int64_t> remapStrings(const json::Object *Strs,
@@ -604,45 +614,234 @@ class RelationalMerger {
       return -1;
     return Map[Local];
   }
-
-  RelationalStringTable Unit, Pass, Name, Function, File;
-  std::vector<int64_t> UnitColG, PassColG, NameColG, TypeColG, FuncColG,
-      FileColG, LineColG, ColumnColG, HotnessColG;
 };
 
 } // namespace
 
+struct RelationalFilter {
+  StringRef Pass;
+  StringRef Name;
+  int64_t Type = -1;
+  StringRef Function;
+  StringRef File;
+  int64_t MinHotness = -1;
+};
+
 static HTTPResult handleGetRemarksRelational(CoreClient &Client,
-                                             StringRef SnapID) {
+                                             StringRef SnapID,
+                                             const RelationalFilter &Filter,
+                                             int64_t Offset, int64_t Limit) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
   SmallVector<UnitRecord, 64> Units =
       Client.storage().metadata().listUnits(SnapID);
   if (Units.empty())
     return makeJSONErrorStr(404, "snapshot has no captured units");
 
+  if (Offset < 0) Offset = 0;
+  if (Limit <= 0) Limit = 10000;
+  if (Limit > 100000) Limit = 100000;
+
   const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
-  RelationalMerger Merger;
-  for (const UnitRecord &Unit : Units) {
-    Expected<json::Array> Results = Client.queryUnit(Unit.ID, Caps);
-    if (!Results) {
-      consumeError(Results.takeError());
-      continue;
+  bool HasFilter = !Filter.Pass.empty() || !Filter.Name.empty() ||
+                   Filter.Type >= 0 || !Filter.Function.empty() ||
+                   !Filter.File.empty() || Filter.MinHotness >= 0;
+
+  auto matchesFilter = [&](const json::Array *PassStrs,
+                           const json::Array *NameStrs,
+                           const json::Array *FuncStrs,
+                           const json::Array *FileStrs,
+                           int64_t PassIdx, int64_t NameIdx, int64_t Type,
+                           int64_t FuncIdx, int64_t FileIdx,
+                           int64_t Hotness) -> bool {
+    if (Filter.Type >= 0 && Type != Filter.Type) return false;
+    if (Filter.MinHotness >= 0 && Hotness < Filter.MinHotness) return false;
+    if (!Filter.Pass.empty()) {
+      if (PassIdx < 0 || PassIdx >= (int64_t)PassStrs->size()) return false;
+      StringRef S = (*PassStrs)[PassIdx].getAsString().value_or("");
+      if (!S.contains_insensitive(Filter.Pass)) return false;
+    }
+    if (!Filter.Name.empty()) {
+      if (NameIdx < 0 || NameIdx >= (int64_t)NameStrs->size()) return false;
+      StringRef S = (*NameStrs)[NameIdx].getAsString().value_or("");
+      if (!S.contains_insensitive(Filter.Name)) return false;
+    }
+    if (!Filter.Function.empty()) {
+      if (FuncIdx < 0 || FuncIdx >= (int64_t)FuncStrs->size()) return false;
+      StringRef S = (*FuncStrs)[FuncIdx].getAsString().value_or("");
+      if (!S.contains_insensitive(Filter.Function)) return false;
+    }
+    if (!Filter.File.empty()) {
+      if (FileIdx < 0 || FileIdx >= (int64_t)FileStrs->size()) return false;
+      StringRef S = (*FileStrs)[FileIdx].getAsString().value_or("");
+      if (!S.contains_insensitive(Filter.File)) return false;
+    }
+    return true;
+  };
+
+  auto getUnitResults = [&](const UnitRecord &U)
+      -> SmallVector<const json::Object *, 1> {
+    SmallVector<const json::Object *, 1> Out;
+    Expected<json::Array> Results = Client.queryUnit(U.ID, Caps);
+    if (!Results) { consumeError(Results.takeError()); return Out; }
+    for (const json::Value &RV : *Results) {
+      const json::Object *RO = RV.getAsObject();
+      if (!RO) continue;
+      if (RO->getString("capability").value_or("") != "llvm.remarks.relational")
+        continue;
+      if (const json::Object *VO = RO->getObject("value"))
+        Out.push_back(VO);
+    }
+    return Out;
+  };
+
+  // Pass 1: count total matching rows (streaming, one unit at a time)
+  int64_t TotalMatching = 0;
+  for (const UnitRecord &U : Units) {
+    Expected<json::Array> Results = Client.queryUnit(U.ID, Caps);
+    if (!Results) { consumeError(Results.takeError()); continue; }
+    for (const json::Value &RV : *Results) {
+      const json::Object *RO = RV.getAsObject();
+      if (!RO || RO->getString("capability").value_or("") != "llvm.remarks.relational")
+        continue;
+      const json::Object *VO = RO->getObject("value");
+      if (!VO) continue;
+      const json::Object *Cols = VO->getObject("columns");
+      const json::Object *Strs = VO->getObject("strings");
+      if (!Cols || !Strs) continue;
+      const json::Array *PassCol = Cols->getArray("pass");
+      if (!PassCol) continue;
+      size_t N = PassCol->size();
+      if (!HasFilter) { TotalMatching += N; continue; }
+      const json::Array *NameCol = Cols->getArray("name");
+      const json::Array *TypeCol = Cols->getArray("type");
+      const json::Array *FuncCol = Cols->getArray("function");
+      const json::Array *FileCol = Cols->getArray("file");
+      const json::Array *HotnessCol = Cols->getArray("hotness");
+      const json::Array *PassStrs = Strs->getArray("pass");
+      const json::Array *NameStrs = Strs->getArray("name");
+      const json::Array *FuncStrs = Strs->getArray("function");
+      const json::Array *FileStrs = Strs->getArray("file");
+      if (!NameCol || !TypeCol || !FuncCol || !FileCol || !HotnessCol ||
+          !PassStrs || !NameStrs || !FuncStrs || !FileStrs) continue;
+      for (size_t I = 0; I < N; ++I) {
+        int64_t PI = (*PassCol)[I].getAsInteger().value_or(-1);
+        int64_t NI = (*NameCol)[I].getAsInteger().value_or(-1);
+        int64_t T  = (*TypeCol)[I].getAsInteger().value_or(-1);
+        int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+        int64_t FiI = (*FileCol)[I].getAsInteger().value_or(-1);
+        int64_t H  = (*HotnessCol)[I].getAsInteger().value_or(-1);
+        if (matchesFilter(PassStrs, NameStrs, FuncStrs, FileStrs, PI, NI, T, FI, FiI, H))
+          ++TotalMatching;
+      }
     }
-    for (const json::Value &ResultValue : *Results) {
-      const json::Object *ResultObj = ResultValue.getAsObject();
-      if (!ResultObj)
+  }
+
+  int64_t Count = std::min(Limit, std::max((int64_t)0, TotalMatching - Offset));
+
+  // Pass 2: collect only the page rows into a small merger
+  RelationalMerger Page;
+  int64_t Seen = 0;
+  int64_t Collected = 0;
+  for (const UnitRecord &U : Units) {
+    if (Collected >= Count) break;
+    Expected<json::Array> Results = Client.queryUnit(U.ID, Caps);
+    if (!Results) { consumeError(Results.takeError()); continue; }
+    for (const json::Value &RV : *Results) {
+      if (Collected >= Count) break;
+      const json::Object *RO = RV.getAsObject();
+      if (!RO || RO->getString("capability").value_or("") != "llvm.remarks.relational")
         continue;
-      std::optional<StringRef> Capability = ResultObj->getString("capability");
-      if (!Capability || *Capability != "llvm.remarks.relational")
+      const json::Object *VO = RO->getObject("value");
+      if (!VO) continue;
+      const json::Object *Cols = VO->getObject("columns");
+      const json::Object *Strs = VO->getObject("strings");
+      if (!Cols || !Strs) continue;
+      const json::Array *PassCol = Cols->getArray("pass");
+      const json::Array *NameCol = Cols->getArray("name");
+      const json::Array *TypeCol = Cols->getArray("type");
+      const json::Array *FuncCol = Cols->getArray("function");
+      const json::Array *FileCol = Cols->getArray("file");
+      const json::Array *LineCol = Cols->getArray("line");
+      const json::Array *ColumnCol = Cols->getArray("column");
+      const json::Array *HotnessCol = Cols->getArray("hotness");
+      const json::Array *PassStrs = Strs->getArray("pass");
+      const json::Array *NameStrs = Strs->getArray("name");
+      const json::Array *FuncStrs = Strs->getArray("function");
+      const json::Array *FileStrs = Strs->getArray("file");
+      if (!PassCol || !NameCol || !TypeCol || !FuncCol || !FileCol ||
+          !LineCol || !ColumnCol || !HotnessCol || !PassStrs || !NameStrs ||
+          !FuncStrs || !FileStrs)
         continue;
-      if (const json::Object *ValueObj = ResultObj->getObject("value"))
-        Merger.absorb(*ValueObj);
+      StringRef UnitID = VO->getString("unit_id").value_or(U.ID);
+      size_t N = PassCol->size();
+      for (size_t I = 0; I < N; ++I) {
+        if (Collected >= Count) break;
+        int64_t PI = (*PassCol)[I].getAsInteger().value_or(-1);
+        int64_t NI = (*NameCol)[I].getAsInteger().value_or(-1);
+        int64_t T  = (*TypeCol)[I].getAsInteger().value_or(-1);
+        int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+        int64_t FiI = (*FileCol)[I].getAsInteger().value_or(-1);
+        int64_t H  = (*HotnessCol)[I].getAsInteger().value_or(-1);
+        if (HasFilter &&
+            !matchesFilter(PassStrs, NameStrs, FuncStrs, FileStrs, PI, NI, T, FI, FiI, H))
+          continue;
+        if (Seen < Offset) { ++Seen; continue; }
+        ++Seen;
+        Page.UnitColG.push_back(static_cast<int64_t>(Page.Unit.getOrAdd(UnitID)));
+        Page.PassColG.push_back(static_cast<int64_t>(
+            Page.Pass.getOrAdd(PI >= 0 ? (*PassStrs)[PI].getAsString().value_or("") : "")));
+        Page.NameColG.push_back(static_cast<int64_t>(
+            Page.Name.getOrAdd(NI >= 0 ? (*NameStrs)[NI].getAsString().value_or("") : "")));
+        Page.TypeColG.push_back(T);
+        Page.FuncColG.push_back(static_cast<int64_t>(
+            Page.Function.getOrAdd(FI >= 0 ? (*FuncStrs)[FI].getAsString().value_or("") : "")));
+        Page.FileColG.push_back(static_cast<int64_t>(
+            Page.File.getOrAdd(FiI >= 0 ? (*FileStrs)[FiI].getAsString().value_or("") : "")));
+        Page.LineColG.push_back((*LineCol)[I].getAsInteger().value_or(-1));
+        Page.ColumnColG.push_back((*ColumnCol)[I].getAsInteger().value_or(-1));
+        Page.HotnessColG.push_back(H);
+        ++Collected;
+      }
     }
   }
 
   std::string Body;
   raw_string_ostream OS(Body);
-  writeSuccessEnvelope(OS,
-                       [&](json::OStream &JOS) { Merger.write(JOS, SnapID); });
+  writeSuccessEnvelope(OS, [&](json::OStream &JOS) {
+    JOS.objectBegin();
+    JOS.attribute("snapshot_id", SnapID);
+    JOS.attribute("schema_version", 1);
+    JOS.attribute("total", TotalMatching);
+    JOS.attribute("offset", Offset);
+    JOS.attribute("limit", Limit);
+    JOS.attribute("count", Collected);
+
+    JOS.attributeBegin("strings");
+    JOS.objectBegin();
+    JOS.attributeBegin("unit");     Page.Unit.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("pass");     Page.Pass.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("name");     Page.Name.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.attributeBegin("function"); Page.Function.writeJSON(JOS); JOS.attributeEnd();
+    JOS.attributeBegin("file");     Page.File.writeJSON(JOS);     JOS.attributeEnd();
+    JOS.objectEnd();
+    JOS.attributeEnd();
+
+    JOS.attributeBegin("columns");
+    JOS.objectBegin();
+    writeInt64Column(JOS, "unit",     Page.UnitColG);
+    writeInt64Column(JOS, "pass",     Page.PassColG);
+    writeInt64Column(JOS, "name",     Page.NameColG);
+    writeInt64Column(JOS, "type",     Page.TypeColG);
+    writeInt64Column(JOS, "function", Page.FuncColG);
+    writeInt64Column(JOS, "file",     Page.FileColG);
+    writeInt64Column(JOS, "line",     Page.LineColG);
+    writeInt64Column(JOS, "column",   Page.ColumnColG);
+    writeInt64Column(JOS, "hotness",  Page.HotnessColG);
+    JOS.objectEnd();
+    JOS.attributeEnd();
+
+    JOS.objectEnd();
+  });
   OS.flush();
   return HTTPResult{200, "application/json", std::move(Body)};
 }
@@ -659,11 +858,28 @@ static HTTPResult handleGetQueryUnit(CoreClient &Client, StringRef UnitID,
 static HTTPResult handleGetQuerySnapshot(CoreClient &Client,
                                          StringRef SnapshotID,
                                          StringRef Capabilities) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
   SmallVector<std::string, 16> Caps = parseCapabilityList(Capabilities);
-  Expected<json::Array> R = Client.querySnapshot(SnapshotID, Caps);
-  if (!R)
-    return makeJSONError(400, R.takeError());
-  return makeJSONSuccess(200, std::move(*R));
+  llvm::erase_if(Caps, [](const std::string &C) {
+    return C == "llvm.remarks.detail";
+  });
+
+  SmallVector<UnitRecord, 64> Units =
+      Client.storage().metadata().listUnits(SnapshotID);
+  if (Units.empty())
+    return makeJSONErrorStr(404, "snapshot has no units");
+
+  static constexpr size_t MaxUnits = 200;
+  size_t Limit = std::min(Units.size(), MaxUnits);
+  json::Array Out;
+  for (size_t I = 0; I < Limit; ++I) {
+    Expected<json::Array> R = Client.queryUnit(Units[I].ID, Caps);
+    if (!R) { consumeError(R.takeError()); continue; }
+    Out.push_back(json::Object{{"unit_id", Units[I].ID},
+                               {"source_path", Units[I].SourcePath},
+                               {"results", std::move(*R)}});
+  }
+  return makeJSONSuccess(200, std::move(Out));
 }
 
 static HTTPResult handleGetCompare(CoreClient &Client, StringRef Before,
@@ -898,8 +1114,32 @@ Error llvm::advisor::HTTPServer::run() {
                     Segs[4] == "mappings" || Segs[4] == "link-units"))
             Res = handleGetEntities(Client, ResolvedSnap, Segs[4]);
           else if (Segs.size() == 6 && Segs[4] == "remarks" &&
-                   Segs[5] == "relational")
-            Res = handleGetRemarksRelational(Client, ResolvedSnap);
+                   Segs[5] == "relational") {
+            RelationalFilter Filter;
+            auto getParam = [&](StringRef K) -> StringRef {
+              auto It = QueryParams.find(K);
+              return It != QueryParams.end() ? StringRef(It->second) : "";
+            };
+            Filter.Pass = getParam("pass");
+            Filter.Name = getParam("name");
+            Filter.Function = getParam("function");
+            Filter.File = getParam("file");
+            auto TypeIt = QueryParams.find("type");
+            if (TypeIt != QueryParams.end())
+              StringRef(TypeIt->second).getAsInteger(10, Filter.Type);
+            auto HotIt = QueryParams.find("min_hotness");
+            if (HotIt != QueryParams.end())
+              StringRef(HotIt->second).getAsInteger(10, Filter.MinHotness);
+            int64_t Offset = 0, Limit = 10000;
+            auto OffIt = QueryParams.find("offset");
+            if (OffIt != QueryParams.end())
+              StringRef(OffIt->second).getAsInteger(10, Offset);
+            auto LimIt = QueryParams.find("limit");
+            if (LimIt != QueryParams.end())
+              StringRef(LimIt->second).getAsInteger(10, Limit);
+            Res = handleGetRemarksRelational(Client, ResolvedSnap, Filter,
+                                            Offset, Limit);
+          }
         } else if (Path == "/api/v1/jobs")
           Res = handleGetJobs(Client);
         else if (IsAPI && Segs.size() == 4 && Segs[2] == "jobs")

>From df06f521aa69fd8d9a4eb8b296754d2c0af20b3b Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Fri, 19 Jun 2026 13:13:23 +0530
Subject: [PATCH 22/41] [llvm-advisor] add Code Explorer with source remarks
 overlay and filtering

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundle.py          |   1 +
 .../src/Client/HTTP/Assets/bundled.html       | 226 ++++++++++++++-
 .../src/Client/HTTP/Assets/core.js            |  14 +-
 .../src/Client/HTTP/Assets/index.html         |   1 +
 .../src/Client/HTTP/Assets/index_html.inc     | 226 ++++++++++++++-
 .../src/Client/HTTP/Assets/shell.js           |   2 +
 .../src/Client/HTTP/Assets/views.js           | 209 +++++++++++++-
 .../src/Client/HTTP/HTTPServer.cpp            | 263 ++++++++++++++++++
 8 files changed, 933 insertions(+), 9 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
index 11a0dcfc6333f..49fb3e9a69fbf 100755
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
@@ -71,6 +71,7 @@ def main():
       Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
+      Router.register('/explorer', () => CodeExplorerView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index f1bb31f4a9a9b..31cdb1c7cd329 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -745,6 +745,7 @@
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
+  explorer: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2,5 H18 M2,9 H14 M2,13 H16 M2,17 H10"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
   chevronRight: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="8,5 13,10 8,15"/></svg>`,
@@ -843,6 +844,17 @@
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  sourceFiles: (snapshotId) => API.get(`/snapshots/${encodeURIComponent(snapshotId)}/files`),
+  source: (snapshotId, path) => API.get(`/source?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`),
+  sourceRemarks: (snapshotId, path, filters) => {
+    let url = `/source/remarks?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`;
+    if (filters) {
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
+    }
+    return API.get(url);
+  },
   insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
   insight: (snapId, name, baseline) => {
     let url = `/snapshots/${snapId}/insights/${name}`;
@@ -954,7 +966,7 @@
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2080,6 +2092,7 @@
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
+      { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2208,6 +2221,7 @@
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
+    { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -4742,7 +4756,16 @@
     viewport.appendChild(spacer);
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex', cursor: 'pointer' } });
+      row.addEventListener('click', () => {
+        const idx = row._idx;
+        if (idx == null || !columns.file) return;
+        const fi = columns.file[idx];
+        if (fi < 0) return;
+        const file = strings.file?.[fi] || '';
+        const line = columns.line[idx];
+        Router.navigate(`/explorer?path=${encodeURIComponent(file)}&line=${line}`);
+      });
       const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
@@ -4779,7 +4802,7 @@
         const idx = first + p;
         const { row, cells } = pool[p];
         if (idx >= len) { row.style.display = 'none'; continue; }
-        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`; row._idx = idx;
         COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
     };
@@ -5090,6 +5113,202 @@
   },
 };
 
+/* ============================================================
+   LLVM Advisor — Code Explorer View
+   ============================================================ */
+
+const CodeExplorerView = {
+  _snap: null,
+  _mainEl: null,
+  _filters: { pass: '', name: '', type: '' },
+
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
+    this._snap = State.get('currentSnapshot');
+    if (!this._snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    container.appendChild(h('div', { class: 'text-muted' }, 'Loading file list...'));
+    Shell.renderMain(container);
+
+    const res = await API.sourceFiles(this._snap.id);
+    if (!res.ok) { container.innerHTML = ''; container.appendChild(UI.errorCard(res.error || 'Failed to load files')); return; }
+    const files = Array.isArray(res.data) ? res.data : [];
+    container.innerHTML = '';
+    if (!files.length) { container.appendChild(UI.emptyCard('No source files', 'No source files with remarks found.')); return; }
+
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'fp-commute', 'aliasing', 'failure'];
+    const TYPE_LABELS = { passed: 'Passed', missed: 'Missed', analysis: 'Analysis', failure: 'Failure' };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '12px', height: 'calc(100vh - 140px)' } });
+    const sidebar = h('div', { style: { width: '240px', minWidth: '180px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+
+    const fileSearch = h('input', { class: 'triage-input', type: 'search', placeholder: 'search files...', style: { width: '100%', flex: 'none' },
+      onInput: (e) => { const q = e.target.value.toLowerCase(); list.querySelectorAll('.explorer-file').forEach(el => { el.style.display = el.dataset.path.toLowerCase().includes(q) ? '' : 'none'; }); }
+    });
+    sidebar.appendChild(fileSearch);
+
+    const list = h('div', { style: { overflow: 'auto', flex: '1' } });
+    files.forEach(f => {
+      const path = f.path || '';
+      const name = path.split('/').pop() || path;
+      const el = h('div', { class: 'explorer-file', 'data-path': path, style: { padding: '5px 8px', cursor: 'pointer', borderRadius: '4px', fontSize: '12px' },
+        onClick: () => { list.querySelectorAll('.explorer-file').forEach(x => x.style.background = ''); el.style.background = 'var(--bg2)'; this._loadFile(path); }
+      },
+        h('div', { style: { fontWeight: '500' } }, name),
+        h('div', { class: 'text-muted mono', style: { fontSize: '10px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, path),
+        h('div', { class: 'text-muted', style: { fontSize: '10px' } }, `${f.remarks_count || 0} remarks`)
+      );
+      list.appendChild(el);
+    });
+    sidebar.appendChild(list);
+
+    const mainCol = h('div', { style: { flex: '1', display: 'flex', flexDirection: 'column', overflow: 'hidden' } });
+
+    const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
+    const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
+    const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
+    ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
+      const enumVal = [1, 2, 3, 6][idx];
+      const chip = h('button', { class: 'triage-chip triage-chip-' + t, style: { fontSize: '11px' } }, TYPE_LABELS[t]);
+      chip.addEventListener('click', () => {
+        if (this._filters.type === String(enumVal)) { this._filters.type = ''; chip.classList.remove('on'); }
+        else { typeChips.querySelectorAll('.on').forEach(c => c.classList.remove('on')); this._filters.type = String(enumVal); chip.classList.add('on'); }
+        this._reloadRemarks();
+      });
+      typeChips.appendChild(chip);
+    });
+    const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    mainCol.appendChild(filterBar);
+
+    let debounce = null;
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    passInput.addEventListener('input', onFilter);
+    nameInput.addEventListener('input', onFilter);
+
+    this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
+    this._remarkCount = remarkCount;
+    mainCol.appendChild(this._mainEl);
+
+    wrap.appendChild(sidebar); wrap.appendChild(mainCol);
+    container.appendChild(wrap);
+
+    const params = State.get('routeParams') || {};
+    const initialPath = params.path || (files.length > 0 ? files[0].path : null);
+    this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
+
+    if (initialPath) {
+      const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
+      if (match) match.style.background = 'var(--bg2)';
+      else if (list.querySelector('.explorer-file')) list.querySelector('.explorer-file').style.background = 'var(--bg2)';
+      this._currentPath = initialPath;
+      this._loadFile(initialPath);
+    }
+  },
+
+  async _loadFile(path) {
+    this._currentPath = path;
+    this._mainEl.innerHTML = '';
+    this._mainEl.appendChild(h('div', { class: 'text-muted', style: { padding: '12px' } }, 'Loading...'));
+
+    const [srcRes, remRes] = await Promise.all([
+      API.source(this._snap.id, path),
+      API.sourceRemarks(this._snap.id, path, this._filters),
+    ]);
+
+    this._mainEl.innerHTML = '';
+    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
+
+    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  async _reloadRemarks() {
+    if (!this._currentPath) return;
+    const res = await API.sourceRemarks(this._snap.id, this._currentPath, this._filters);
+    this._remarks = (res.ok && res.data) ? res.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  _renderSource() {
+    const lines = this._sourceLines || [];
+    const remarks = this._remarks || [];
+    const container = this._mainEl;
+    container.innerHTML = '';
+
+    const remarksByLine = {};
+    for (const r of remarks) {
+      if (r.line < 1) continue;
+      if (!remarksByLine[r.line]) remarksByLine[r.line] = [];
+      remarksByLine[r.line].push(r);
+    }
+
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_BG = { 2: 'rgba(255,179,71,0.08)', 6: 'rgba(255,107,110,0.08)' };
+
+    const header = h('div', { style: { padding: '6px 12px', borderBottom: '1px solid var(--border)', fontSize: '12px', display: 'flex', justifyContent: 'space-between' } },
+      h('span', { class: 'mono', style: { fontWeight: '500' } }, (this._currentPath || '').split('/').pop()),
+      h('span', { class: 'text-muted' }, `${Object.keys(remarksByLine).length} lines with remarks`)
+    );
+    container.appendChild(header);
+
+    const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
+    lines.forEach((line, i) => {
+      const ln = i + 1;
+      const rems = remarksByLine[ln];
+      const has = rems && rems.length > 0;
+      const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
+      const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
+      if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
+
+      const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
+      const row = h('div', { style: rowStyle },
+        h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
+        h('span', { style: { flex: '1', whiteSpace: 'pre', overflow: 'hidden' } }, line || ' '),
+        badge
+      );
+
+      if (has) {
+        row.addEventListener('click', () => {
+          const id = `rem-${ln}`;
+          const existing = codeWrap.querySelector(`#${id}`);
+          if (existing) { existing.remove(); return; }
+          const detail = h('div', { id, style: { padding: '4px 12px 4px 56px', background: 'var(--bg2)', borderLeft: '3px solid ' + color, fontSize: '11px' } });
+          rems.forEach(r => {
+            detail.appendChild(h('div', { style: { padding: '2px 0', display: 'flex', gap: '8px', alignItems: 'baseline' } },
+              h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--text-muted)', fontWeight: '600', minWidth: '55px' } }, TYPE_NAMES[r.type] || '?'),
+              h('span', { style: { fontWeight: '500' } }, r.name || ''),
+              h('span', { class: 'text-muted' }, r.pass || ''),
+              r.function ? h('span', { class: 'text-muted' }, `in ${r.function}`) : null,
+              r.hotness != null && r.hotness >= 0 ? h('span', { style: { color: 'var(--orange)', fontSize: '10px' } }, `hot:${r.hotness}`) : null,
+            ));
+          });
+          row.after(detail);
+        });
+      }
+      codeWrap.appendChild(row);
+    });
+    container.appendChild(codeWrap);
+
+    if (this._scrollToLine > 0) {
+      requestAnimationFrame(() => {
+        container.scrollTop = Math.max(0, (this._scrollToLine - 1) * 20 - 100);
+        this._scrollToLine = 0;
+      });
+    }
+  },
+};
+
   </script>
   <script>
     (function() {
@@ -5101,6 +5320,7 @@
       Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
+      Router.register('/explorer', () => CodeExplorerView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index 5ebb899f6dd87..576a6664f7381 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -13,6 +13,7 @@ const Icons = {
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
+  explorer: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2,5 H18 M2,9 H14 M2,13 H16 M2,17 H10"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
   chevronRight: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="8,5 13,10 8,15"/></svg>`,
@@ -111,6 +112,17 @@ const API = {
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  sourceFiles: (snapshotId) => API.get(`/snapshots/${encodeURIComponent(snapshotId)}/files`),
+  source: (snapshotId, path) => API.get(`/source?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`),
+  sourceRemarks: (snapshotId, path, filters) => {
+    let url = `/source/remarks?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`;
+    if (filters) {
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
+    }
+    return API.get(url);
+  },
   insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
   insight: (snapId, name, baseline) => {
     let url = `/snapshots/${snapId}/insights/${name}`;
@@ -222,7 +234,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
index ccd0f67b22acf..9e05cff690c06 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
@@ -28,6 +28,7 @@
       Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
+      Router.register('/explorer', () => CodeExplorerView.render());
       Router.register('/settings', () => SettingsView.render());
 
       Shell.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 829e5568dad6d..b628429e876d9 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -748,6 +748,7 @@ const Icons = {
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
+  explorer: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2,5 H18 M2,9 H14 M2,13 H16 M2,17 H10"/></svg>`,
   search: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8.5" cy="8.5" r="5"/><line x1="12.5" y1="12.5" x2="17" y2="17"/></svg>`,
   chevronDown: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5,8 10,13 15,8"/></svg>`,
   chevronRight: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2"><polyline points="8,5 13,10 8,15"/></svg>`,
@@ -846,6 +847,17 @@ const API = {
   capabilities: () => API.get('/capabilities'),
   queryUnit: (unitId, caps) => API.get(`/query/unit/${encodeURIComponent(unitId)}/${(caps || []).join(',')}`),
   querySnapshot: (snapshotId, caps) => API.get(`/query/snapshot/${encodeURIComponent(snapshotId)}/${(caps || []).join(',')}`),
+  sourceFiles: (snapshotId) => API.get(`/snapshots/${encodeURIComponent(snapshotId)}/files`),
+  source: (snapshotId, path) => API.get(`/source?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`),
+  sourceRemarks: (snapshotId, path, filters) => {
+    let url = `/source/remarks?path=${encodeURIComponent(path)}&snapshot_id=${encodeURIComponent(snapshotId)}`;
+    if (filters) {
+      if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
+      if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
+    }
+    return API.get(url);
+  },
   insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
   insight: (snapId, name, baseline) => {
     let url = `/snapshots/${snapId}/insights/${name}`;
@@ -957,7 +969,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2083,6 +2095,7 @@ const Shell = {
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
+      { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -2211,6 +2224,7 @@ const CommandPalette = {
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
+    { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
@@ -4745,7 +4759,16 @@ const RemarksView = {
     viewport.appendChild(spacer);
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex', cursor: 'pointer' } });
+      row.addEventListener('click', () => {
+        const idx = row._idx;
+        if (idx == null || !columns.file) return;
+        const fi = columns.file[idx];
+        if (fi < 0) return;
+        const file = strings.file?.[fi] || '';
+        const line = columns.line[idx];
+        Router.navigate(`/explorer?path=${encodeURIComponent(file)}&line=${line}`);
+      });
       const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
@@ -4782,7 +4805,7 @@ const RemarksView = {
         const idx = first + p;
         const { row, cells } = pool[p];
         if (idx >= len) { row.style.display = 'none'; continue; }
-        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`; row._idx = idx;
         COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
     };
@@ -5093,6 +5116,202 @@ const HeatmapView = {
   },
 };
 
+/* ============================================================
+   LLVM Advisor — Code Explorer View
+   ============================================================ */
+
+const CodeExplorerView = {
+  _snap: null,
+  _mainEl: null,
+  _filters: { pass: '', name: '', type: '' },
+
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
+    this._snap = State.get('currentSnapshot');
+    if (!this._snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    container.appendChild(h('div', { class: 'text-muted' }, 'Loading file list...'));
+    Shell.renderMain(container);
+
+    const res = await API.sourceFiles(this._snap.id);
+    if (!res.ok) { container.innerHTML = ''; container.appendChild(UI.errorCard(res.error || 'Failed to load files')); return; }
+    const files = Array.isArray(res.data) ? res.data : [];
+    container.innerHTML = '';
+    if (!files.length) { container.appendChild(UI.emptyCard('No source files', 'No source files with remarks found.')); return; }
+
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'fp-commute', 'aliasing', 'failure'];
+    const TYPE_LABELS = { passed: 'Passed', missed: 'Missed', analysis: 'Analysis', failure: 'Failure' };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '12px', height: 'calc(100vh - 140px)' } });
+    const sidebar = h('div', { style: { width: '240px', minWidth: '180px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+
+    const fileSearch = h('input', { class: 'triage-input', type: 'search', placeholder: 'search files...', style: { width: '100%', flex: 'none' },
+      onInput: (e) => { const q = e.target.value.toLowerCase(); list.querySelectorAll('.explorer-file').forEach(el => { el.style.display = el.dataset.path.toLowerCase().includes(q) ? '' : 'none'; }); }
+    });
+    sidebar.appendChild(fileSearch);
+
+    const list = h('div', { style: { overflow: 'auto', flex: '1' } });
+    files.forEach(f => {
+      const path = f.path || '';
+      const name = path.split('/').pop() || path;
+      const el = h('div', { class: 'explorer-file', 'data-path': path, style: { padding: '5px 8px', cursor: 'pointer', borderRadius: '4px', fontSize: '12px' },
+        onClick: () => { list.querySelectorAll('.explorer-file').forEach(x => x.style.background = ''); el.style.background = 'var(--bg2)'; this._loadFile(path); }
+      },
+        h('div', { style: { fontWeight: '500' } }, name),
+        h('div', { class: 'text-muted mono', style: { fontSize: '10px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, path),
+        h('div', { class: 'text-muted', style: { fontSize: '10px' } }, `${f.remarks_count || 0} remarks`)
+      );
+      list.appendChild(el);
+    });
+    sidebar.appendChild(list);
+
+    const mainCol = h('div', { style: { flex: '1', display: 'flex', flexDirection: 'column', overflow: 'hidden' } });
+
+    const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
+    const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
+    const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
+    ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
+      const enumVal = [1, 2, 3, 6][idx];
+      const chip = h('button', { class: 'triage-chip triage-chip-' + t, style: { fontSize: '11px' } }, TYPE_LABELS[t]);
+      chip.addEventListener('click', () => {
+        if (this._filters.type === String(enumVal)) { this._filters.type = ''; chip.classList.remove('on'); }
+        else { typeChips.querySelectorAll('.on').forEach(c => c.classList.remove('on')); this._filters.type = String(enumVal); chip.classList.add('on'); }
+        this._reloadRemarks();
+      });
+      typeChips.appendChild(chip);
+    });
+    const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    mainCol.appendChild(filterBar);
+
+    let debounce = null;
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    passInput.addEventListener('input', onFilter);
+    nameInput.addEventListener('input', onFilter);
+
+    this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
+    this._remarkCount = remarkCount;
+    mainCol.appendChild(this._mainEl);
+
+    wrap.appendChild(sidebar); wrap.appendChild(mainCol);
+    container.appendChild(wrap);
+
+    const params = State.get('routeParams') || {};
+    const initialPath = params.path || (files.length > 0 ? files[0].path : null);
+    this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
+
+    if (initialPath) {
+      const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
+      if (match) match.style.background = 'var(--bg2)';
+      else if (list.querySelector('.explorer-file')) list.querySelector('.explorer-file').style.background = 'var(--bg2)';
+      this._currentPath = initialPath;
+      this._loadFile(initialPath);
+    }
+  },
+
+  async _loadFile(path) {
+    this._currentPath = path;
+    this._mainEl.innerHTML = '';
+    this._mainEl.appendChild(h('div', { class: 'text-muted', style: { padding: '12px' } }, 'Loading...'));
+
+    const [srcRes, remRes] = await Promise.all([
+      API.source(this._snap.id, path),
+      API.sourceRemarks(this._snap.id, path, this._filters),
+    ]);
+
+    this._mainEl.innerHTML = '';
+    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
+
+    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  async _reloadRemarks() {
+    if (!this._currentPath) return;
+    const res = await API.sourceRemarks(this._snap.id, this._currentPath, this._filters);
+    this._remarks = (res.ok && res.data) ? res.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  _renderSource() {
+    const lines = this._sourceLines || [];
+    const remarks = this._remarks || [];
+    const container = this._mainEl;
+    container.innerHTML = '';
+
+    const remarksByLine = {};
+    for (const r of remarks) {
+      if (r.line < 1) continue;
+      if (!remarksByLine[r.line]) remarksByLine[r.line] = [];
+      remarksByLine[r.line].push(r);
+    }
+
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_BG = { 2: 'rgba(255,179,71,0.08)', 6: 'rgba(255,107,110,0.08)' };
+
+    const header = h('div', { style: { padding: '6px 12px', borderBottom: '1px solid var(--border)', fontSize: '12px', display: 'flex', justifyContent: 'space-between' } },
+      h('span', { class: 'mono', style: { fontWeight: '500' } }, (this._currentPath || '').split('/').pop()),
+      h('span', { class: 'text-muted' }, `${Object.keys(remarksByLine).length} lines with remarks`)
+    );
+    container.appendChild(header);
+
+    const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
+    lines.forEach((line, i) => {
+      const ln = i + 1;
+      const rems = remarksByLine[ln];
+      const has = rems && rems.length > 0;
+      const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
+      const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
+      if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
+
+      const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
+      const row = h('div', { style: rowStyle },
+        h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
+        h('span', { style: { flex: '1', whiteSpace: 'pre', overflow: 'hidden' } }, line || ' '),
+        badge
+      );
+
+      if (has) {
+        row.addEventListener('click', () => {
+          const id = `rem-${ln}`;
+          const existing = codeWrap.querySelector(`#${id}`);
+          if (existing) { existing.remove(); return; }
+          const detail = h('div', { id, style: { padding: '4px 12px 4px 56px', background: 'var(--bg2)', borderLeft: '3px solid ' + color, fontSize: '11px' } });
+          rems.forEach(r => {
+            detail.appendChild(h('div', { style: { padding: '2px 0', display: 'flex', gap: '8px', alignItems: 'baseline' } },
+              h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--text-muted)', fontWeight: '600', minWidth: '55px' } }, TYPE_NAMES[r.type] || '?'),
+              h('span', { style: { fontWeight: '500' } }, r.name || ''),
+              h('span', { class: 'text-muted' }, r.pass || ''),
+              r.function ? h('span', { class: 'text-muted' }, `in ${r.function}`) : null,
+              r.hotness != null && r.hotness >= 0 ? h('span', { style: { color: 'var(--orange)', fontSize: '10px' } }, `hot:${r.hotness}`) : null,
+            ));
+          });
+          row.after(detail);
+        });
+      }
+      codeWrap.appendChild(row);
+    });
+    container.appendChild(codeWrap);
+
+    if (this._scrollToLine > 0) {
+      requestAnimationFrame(() => {
+        container.scrollTop = Math.max(0, (this._scrollToLine - 1) * 20 - 100);
+        this._scrollToLine = 0;
+      });
+    }
+  },
+};
+
   </script>
   <script>
     (function() {
@@ -5104,6 +5323,7 @@ const HeatmapView = {
       Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
+      Router.register('/explorer', () => CodeExplorerView.render());
       Router.register('/settings', () => SettingsView.render());
       Shell.init();
       Keys.init();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
index 2e5c9570fc89b..66421ab7db490 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
@@ -79,6 +79,7 @@ const Shell = {
       { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
+      { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
       { icon: 'settings', label: 'Settings', route: '/settings', shortcut: 'g s' },
     ];
 
@@ -207,6 +208,7 @@ const CommandPalette = {
     { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
+    { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
     { label: 'Go to Settings', shortcut: 'g s', action: () => Router.navigate('/settings') },
   ],
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 8d0def52ccc31..e650814fe0f3d 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -988,7 +988,16 @@ const RemarksView = {
     viewport.appendChild(spacer);
     const pool = [];
     for (let p = 0; p < POOL_SIZE; p++) {
-      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex' } });
+      const row = h('div', { class: 'triage-row', style: { height: ROW_H + 'px', display: 'flex', cursor: 'pointer' } });
+      row.addEventListener('click', () => {
+        const idx = row._idx;
+        if (idx == null || !columns.file) return;
+        const fi = columns.file[idx];
+        if (fi < 0) return;
+        const file = strings.file?.[fi] || '';
+        const line = columns.line[idx];
+        Router.navigate(`/explorer?path=${encodeURIComponent(file)}&line=${line}`);
+      });
       const cells = COLS.map(col => h('span', { class: `triage-td${col.mono ? ' mono' : ''}${col.align === 'right' ? ' right' : ''}`, style: { ...colStyle(col), overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, ''));
       cells.forEach(c => row.appendChild(c));
       spacer.appendChild(row);
@@ -1025,7 +1034,7 @@ const RemarksView = {
         const idx = first + p;
         const { row, cells } = pool[p];
         if (idx >= len) { row.style.display = 'none'; continue; }
-        row.style.display = ''; row.style.top = `${idx * ROW_H}px`;
+        row.style.display = ''; row.style.top = `${idx * ROW_H}px`; row._idx = idx;
         COLS.forEach((col, c) => { const v = getCell(idx, col.id) || '–'; cells[c].textContent = v; cells[c].title = v; });
       }
     };
@@ -1335,3 +1344,199 @@ const HeatmapView = {
     container.appendChild(table);
   },
 };
+
+/* ============================================================
+   LLVM Advisor — Code Explorer View
+   ============================================================ */
+
+const CodeExplorerView = {
+  _snap: null,
+  _mainEl: null,
+  _filters: { pass: '', name: '', type: '' },
+
+  async render() {
+    const container = h('div', {});
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
+    this._snap = State.get('currentSnapshot');
+    if (!this._snap) {
+      container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
+      Shell.renderMain(container);
+      return;
+    }
+
+    container.appendChild(h('div', { class: 'text-muted' }, 'Loading file list...'));
+    Shell.renderMain(container);
+
+    const res = await API.sourceFiles(this._snap.id);
+    if (!res.ok) { container.innerHTML = ''; container.appendChild(UI.errorCard(res.error || 'Failed to load files')); return; }
+    const files = Array.isArray(res.data) ? res.data : [];
+    container.innerHTML = '';
+    if (!files.length) { container.appendChild(UI.emptyCard('No source files', 'No source files with remarks found.')); return; }
+
+    const TYPE_NAMES = ['unknown', 'passed', 'missed', 'analysis', 'fp-commute', 'aliasing', 'failure'];
+    const TYPE_LABELS = { passed: 'Passed', missed: 'Missed', analysis: 'Analysis', failure: 'Failure' };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '12px', height: 'calc(100vh - 140px)' } });
+    const sidebar = h('div', { style: { width: '240px', minWidth: '180px', display: 'flex', flexDirection: 'column', gap: '6px' } });
+
+    const fileSearch = h('input', { class: 'triage-input', type: 'search', placeholder: 'search files...', style: { width: '100%', flex: 'none' },
+      onInput: (e) => { const q = e.target.value.toLowerCase(); list.querySelectorAll('.explorer-file').forEach(el => { el.style.display = el.dataset.path.toLowerCase().includes(q) ? '' : 'none'; }); }
+    });
+    sidebar.appendChild(fileSearch);
+
+    const list = h('div', { style: { overflow: 'auto', flex: '1' } });
+    files.forEach(f => {
+      const path = f.path || '';
+      const name = path.split('/').pop() || path;
+      const el = h('div', { class: 'explorer-file', 'data-path': path, style: { padding: '5px 8px', cursor: 'pointer', borderRadius: '4px', fontSize: '12px' },
+        onClick: () => { list.querySelectorAll('.explorer-file').forEach(x => x.style.background = ''); el.style.background = 'var(--bg2)'; this._loadFile(path); }
+      },
+        h('div', { style: { fontWeight: '500' } }, name),
+        h('div', { class: 'text-muted mono', style: { fontSize: '10px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, path),
+        h('div', { class: 'text-muted', style: { fontSize: '10px' } }, `${f.remarks_count || 0} remarks`)
+      );
+      list.appendChild(el);
+    });
+    sidebar.appendChild(list);
+
+    const mainCol = h('div', { style: { flex: '1', display: 'flex', flexDirection: 'column', overflow: 'hidden' } });
+
+    const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
+    const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
+    const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
+    ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
+      const enumVal = [1, 2, 3, 6][idx];
+      const chip = h('button', { class: 'triage-chip triage-chip-' + t, style: { fontSize: '11px' } }, TYPE_LABELS[t]);
+      chip.addEventListener('click', () => {
+        if (this._filters.type === String(enumVal)) { this._filters.type = ''; chip.classList.remove('on'); }
+        else { typeChips.querySelectorAll('.on').forEach(c => c.classList.remove('on')); this._filters.type = String(enumVal); chip.classList.add('on'); }
+        this._reloadRemarks();
+      });
+      typeChips.appendChild(chip);
+    });
+    const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    mainCol.appendChild(filterBar);
+
+    let debounce = null;
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    passInput.addEventListener('input', onFilter);
+    nameInput.addEventListener('input', onFilter);
+
+    this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
+    this._remarkCount = remarkCount;
+    mainCol.appendChild(this._mainEl);
+
+    wrap.appendChild(sidebar); wrap.appendChild(mainCol);
+    container.appendChild(wrap);
+
+    const params = State.get('routeParams') || {};
+    const initialPath = params.path || (files.length > 0 ? files[0].path : null);
+    this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
+
+    if (initialPath) {
+      const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
+      if (match) match.style.background = 'var(--bg2)';
+      else if (list.querySelector('.explorer-file')) list.querySelector('.explorer-file').style.background = 'var(--bg2)';
+      this._currentPath = initialPath;
+      this._loadFile(initialPath);
+    }
+  },
+
+  async _loadFile(path) {
+    this._currentPath = path;
+    this._mainEl.innerHTML = '';
+    this._mainEl.appendChild(h('div', { class: 'text-muted', style: { padding: '12px' } }, 'Loading...'));
+
+    const [srcRes, remRes] = await Promise.all([
+      API.source(this._snap.id, path),
+      API.sourceRemarks(this._snap.id, path, this._filters),
+    ]);
+
+    this._mainEl.innerHTML = '';
+    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
+
+    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  async _reloadRemarks() {
+    if (!this._currentPath) return;
+    const res = await API.sourceRemarks(this._snap.id, this._currentPath, this._filters);
+    this._remarks = (res.ok && res.data) ? res.data.remarks || [] : [];
+    this._remarkCount.textContent = `${this._remarks.length} remarks`;
+    this._renderSource();
+  },
+
+  _renderSource() {
+    const lines = this._sourceLines || [];
+    const remarks = this._remarks || [];
+    const container = this._mainEl;
+    container.innerHTML = '';
+
+    const remarksByLine = {};
+    for (const r of remarks) {
+      if (r.line < 1) continue;
+      if (!remarksByLine[r.line]) remarksByLine[r.line] = [];
+      remarksByLine[r.line].push(r);
+    }
+
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_BG = { 2: 'rgba(255,179,71,0.08)', 6: 'rgba(255,107,110,0.08)' };
+
+    const header = h('div', { style: { padding: '6px 12px', borderBottom: '1px solid var(--border)', fontSize: '12px', display: 'flex', justifyContent: 'space-between' } },
+      h('span', { class: 'mono', style: { fontWeight: '500' } }, (this._currentPath || '').split('/').pop()),
+      h('span', { class: 'text-muted' }, `${Object.keys(remarksByLine).length} lines with remarks`)
+    );
+    container.appendChild(header);
+
+    const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
+    lines.forEach((line, i) => {
+      const ln = i + 1;
+      const rems = remarksByLine[ln];
+      const has = rems && rems.length > 0;
+      const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
+      const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
+      if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
+
+      const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
+      const row = h('div', { style: rowStyle },
+        h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
+        h('span', { style: { flex: '1', whiteSpace: 'pre', overflow: 'hidden' } }, line || ' '),
+        badge
+      );
+
+      if (has) {
+        row.addEventListener('click', () => {
+          const id = `rem-${ln}`;
+          const existing = codeWrap.querySelector(`#${id}`);
+          if (existing) { existing.remove(); return; }
+          const detail = h('div', { id, style: { padding: '4px 12px 4px 56px', background: 'var(--bg2)', borderLeft: '3px solid ' + color, fontSize: '11px' } });
+          rems.forEach(r => {
+            detail.appendChild(h('div', { style: { padding: '2px 0', display: 'flex', gap: '8px', alignItems: 'baseline' } },
+              h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--text-muted)', fontWeight: '600', minWidth: '55px' } }, TYPE_NAMES[r.type] || '?'),
+              h('span', { style: { fontWeight: '500' } }, r.name || ''),
+              h('span', { class: 'text-muted' }, r.pass || ''),
+              r.function ? h('span', { class: 'text-muted' }, `in ${r.function}`) : null,
+              r.hotness != null && r.hotness >= 0 ? h('span', { style: { color: 'var(--orange)', fontSize: '10px' } }, `hot:${r.hotness}`) : null,
+            ));
+          });
+          row.after(detail);
+        });
+      }
+      codeWrap.appendChild(row);
+    });
+    container.appendChild(codeWrap);
+
+    if (this._scrollToLine > 0) {
+      requestAnimationFrame(() => {
+        container.scrollTop = Math.max(0, (this._scrollToLine - 1) * 20 - 100);
+        this._scrollToLine = 0;
+      });
+    }
+  },
+};
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 3da1334d0556a..be6cf851d9f09 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -15,6 +15,9 @@
 #include "Client/HTTP/HTTPServer.h"
 #include "Client/HTTP/Handlers/StaticHandler.h"
 #include "Utils/JSON.h"
+#include "Utils/Normalization.h"
+
+#include "llvm/Support/MemoryBuffer.h"
 
 #include <cerrno>
 #include <cstring>
@@ -846,6 +849,236 @@ static HTTPResult handleGetRemarksRelational(CoreClient &Client,
   return HTTPResult{200, "application/json", std::move(Body)};
 }
 
+static HTTPResult handleGetSourceFiles(CoreClient &Client,
+                                       StringRef SnapID) {
+  const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
+  Expected<json::Array> Query = Client.querySnapshot(SnapID, Caps);
+  if (!Query)
+    return makeJSONError(400, Query.takeError());
+
+  StringMap<int64_t> FileCounts;
+  for (const json::Value &UnitValue : *Query) {
+    const json::Object *UnitObj = UnitValue.getAsObject();
+    const json::Array *Results =
+        UnitObj ? UnitObj->getArray("results") : nullptr;
+    if (!Results)
+      continue;
+    for (const json::Value &ResultValue : *Results) {
+      const json::Object *ResultObj = ResultValue.getAsObject();
+      const json::Object *ValueObj =
+          ResultObj ? ResultObj->getObject("value") : nullptr;
+      if (!ValueObj)
+        continue;
+      std::optional<StringRef> Capability =
+          ResultObj->getString("capability");
+      if (!Capability || *Capability != "llvm.remarks.relational")
+        continue;
+      const json::Object *Cols = ValueObj->getObject("columns");
+      const json::Object *Strs = ValueObj->getObject("strings");
+      if (!Cols || !Strs)
+        continue;
+      const json::Array *FileCol = Cols->getArray("file");
+      const json::Array *FileStrs = Strs->getArray("file");
+      if (!FileCol || !FileStrs)
+        continue;
+      for (const json::Value &V : *FileCol) {
+        std::optional<int64_t> Idx = V.getAsInteger();
+        if (!Idx || *Idx < 0 ||
+            *Idx >= static_cast<int64_t>(FileStrs->size()))
+          continue;
+        StringRef FilePath =
+            (*FileStrs)[static_cast<size_t>(*Idx)]
+                .getAsString()
+                .value_or("");
+        if (!FilePath.empty())
+          FileCounts[FilePath] += 1;
+      }
+    }
+  }
+
+  json::Array Files;
+  for (const auto &KV : FileCounts) {
+    Files.push_back(
+        json::Object{{"path", KV.first()}, {"remarks_count", KV.second}});
+  }
+  std::sort(Files.begin(), Files.end(),
+            [](const json::Value &A, const json::Value &B) {
+              const json::Object *OA = A.getAsObject();
+              const json::Object *OB = B.getAsObject();
+              int64_t CA =
+                  OA ? OA->getInteger("remarks_count").value_or(0) : 0;
+              int64_t CB =
+                  OB ? OB->getInteger("remarks_count").value_or(0) : 0;
+              return CA > CB;
+            });
+  return makeJSONSuccess(200, std::move(Files));
+}
+
+static HTTPResult handleGetSource(CoreClient &Client, StringRef SnapID,
+                                  StringRef FilePath) {
+  Expected<SnapshotRecord> Snap =
+      Client.storage().metadata().getSnapshot(SnapID);
+  if (!Snap)
+    return makeJSONError(404, Snap.takeError());
+
+  SmallVector<StringRef, 2> Roots;
+  if (!Snap->SourceRoot.empty())
+    Roots.push_back(Snap->SourceRoot);
+  if (!Snap->BuildRoot.empty())
+    Roots.push_back(Snap->BuildRoot);
+
+  if (Roots.empty())
+    return makeJSONErrorStr(400, "snapshot has no source or build root");
+
+  std::string ResolvedPath;
+  bool Found = false;
+
+  if (sys::path::is_absolute(FilePath)) {
+    Expected<std::string> R = canonicalizePath(FilePath, Roots);
+    if (R) { ResolvedPath = std::move(*R); Found = true; }
+    else {
+      consumeError(R.takeError());
+      SmallString<256> Real;
+      if (!sys::fs::real_path(FilePath, Real)) {
+        ResolvedPath = std::string(Real);
+        Found = true;
+      }
+    }
+  }
+
+  if (!Found) {
+    for (StringRef Root : Roots) {
+      for (StringRef Base : {Root, StringRef(sys::path::parent_path(Root))}) {
+        SmallString<256> Joined(Base);
+        sys::path::append(Joined, FilePath);
+        if (sys::fs::exists(Joined)) {
+          SmallString<256> Real;
+          if (!sys::fs::real_path(Joined, Real)) {
+            ResolvedPath = std::string(Real);
+            Found = true;
+            break;
+          }
+        }
+      }
+      if (Found) break;
+    }
+  }
+
+  if (!Found)
+    return makeJSONErrorStr(404, "source file not found");
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
+      MemoryBuffer::getFile(ResolvedPath);
+  if (!Buf)
+    return makeJSONErrorStr(404, "source file not found");
+
+  StringRef Content = (*Buf)->getBuffer();
+  json::Object Result;
+  Result["path"] = ResolvedPath;
+  Result["content"] = Content.str();
+  Result["lines"] = static_cast<int64_t>(
+                        std::count(Content.begin(), Content.end(), '\n')) +
+                    1;
+  return makeJSONSuccess(200, std::move(Result));
+}
+
+static HTTPResult handleGetSourceRemarks(CoreClient &Client, StringRef SnapID,
+                                         StringRef FilePath, StringRef FilterPass,
+                                         StringRef FilterName, int64_t FilterType) {
+  if (FilePath.empty())
+    return makeJSONErrorStr(400, "path parameter is required");
+
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
+  const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
+  SmallVector<UnitRecord, 64> Units =
+      Client.storage().metadata().listUnits(SnapID);
+
+  std::string Body;
+  raw_string_ostream OS(Body);
+  int64_t Count = 0;
+
+  writeSuccessEnvelope(OS, [&](json::OStream &JOS) {
+    JOS.object([&] {
+      JOS.attribute("path", FilePath);
+      JOS.attributeBegin("remarks");
+      JOS.arrayBegin();
+
+      for (const UnitRecord &Unit : Units) {
+        Expected<json::Array> Results = Client.queryUnit(Unit.ID, Caps);
+        if (!Results) { consumeError(Results.takeError()); continue; }
+        for (const json::Value &RV : *Results) {
+          const json::Object *RO = RV.getAsObject();
+          if (!RO) continue;
+          if (RO->getString("capability").value_or("") != "llvm.remarks.relational")
+            continue;
+          const json::Object *VO = RO->getObject("value");
+          if (!VO) continue;
+          const json::Object *Cols = VO->getObject("columns");
+          const json::Object *Strs = VO->getObject("strings");
+          if (!Cols || !Strs) continue;
+          const json::Array *FileCol = Cols->getArray("file");
+          const json::Array *FileStrs = Strs->getArray("file");
+          const json::Array *LineCol = Cols->getArray("line");
+          const json::Array *ColumnCol = Cols->getArray("column");
+          const json::Array *PassCol = Cols->getArray("pass");
+          const json::Array *NameCol = Cols->getArray("name");
+          const json::Array *TypeCol = Cols->getArray("type");
+          const json::Array *HotnessCol = Cols->getArray("hotness");
+          const json::Array *FuncCol = Cols->getArray("function");
+          const json::Array *PassStrs = Strs->getArray("pass");
+          const json::Array *NameStrs = Strs->getArray("name");
+          const json::Array *FuncStrs = Strs->getArray("function");
+          if (!FileCol || !FileStrs || !LineCol || !ColumnCol || !PassCol ||
+              !NameCol || !TypeCol || !HotnessCol || !FuncCol || !PassStrs ||
+              !NameStrs || !FuncStrs)
+            continue;
+
+          int64_t TargetIdx = -1;
+          for (size_t I = 0; I < FileStrs->size(); ++I) {
+            std::optional<StringRef> S = (*FileStrs)[I].getAsString();
+            if (S && *S == FilePath) { TargetIdx = I; break; }
+          }
+          if (TargetIdx < 0) continue;
+
+          for (size_t I = 0; I < FileCol->size(); ++I) {
+            if ((*FileCol)[I].getAsInteger().value_or(-1) != TargetIdx) continue;
+            int64_t PI = (*PassCol)[I].getAsInteger().value_or(-1);
+            int64_t NI = (*NameCol)[I].getAsInteger().value_or(-1);
+            int64_t T = (*TypeCol)[I].getAsInteger().value_or(-1);
+            if (FilterType >= 0 && T != FilterType) continue;
+            StringRef PassStr = PI >= 0 && PI < (int64_t)PassStrs->size()
+                ? (*PassStrs)[PI].getAsString().value_or("") : "";
+            StringRef NameStr = NI >= 0 && NI < (int64_t)NameStrs->size()
+                ? (*NameStrs)[NI].getAsString().value_or("") : "";
+            if (!FilterPass.empty() && !PassStr.contains_insensitive(FilterPass)) continue;
+            if (!FilterName.empty() && !NameStr.contains_insensitive(FilterName)) continue;
+
+            int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+            JOS.object([&] {
+              JOS.attribute("line", (*LineCol)[I].getAsInteger().value_or(-1));
+              JOS.attribute("column", (*ColumnCol)[I].getAsInteger().value_or(-1));
+              JOS.attribute("type", T);
+              JOS.attribute("pass", PassStr);
+              JOS.attribute("name", NameStr);
+              int64_t H = (*HotnessCol)[I].getAsInteger().value_or(-1);
+              if (H >= 0) JOS.attribute("hotness", H);
+              if (FI >= 0 && FI < (int64_t)FuncStrs->size())
+                JOS.attribute("function", (*FuncStrs)[FI].getAsString().value_or(""));
+            });
+            ++Count;
+          }
+        }
+      }
+
+      JOS.arrayEnd();
+      JOS.attributeEnd();
+      JOS.attribute("count", Count);
+    });
+  });
+  OS.flush();
+  return HTTPResult{200, "application/json", std::move(Body)};
+}
+
 static HTTPResult handleGetQueryUnit(CoreClient &Client, StringRef UnitID,
                                      StringRef Capabilities) {
   SmallVector<std::string, 16> Caps = parseCapabilityList(Capabilities);
@@ -1140,6 +1373,36 @@ Error llvm::advisor::HTTPServer::run() {
             Res = handleGetRemarksRelational(Client, ResolvedSnap, Filter,
                                             Offset, Limit);
           }
+          else if (Segs.size() == 5 && Segs[4] == "files")
+            Res = handleGetSourceFiles(Client, ResolvedSnap);
+        } else if (Path == "/api/v1/source/remarks") {
+          auto PathIt = QueryParams.find("path");
+          auto SnapIt = QueryParams.find("snapshot_id");
+          if (PathIt == QueryParams.end() || SnapIt == QueryParams.end())
+            Res = makeJSONErrorStr(400, "path and snapshot_id required");
+          else {
+            StringRef FPass, FName;
+            int64_t FType = -1;
+            auto PIt = QueryParams.find("pass");
+            if (PIt != QueryParams.end()) FPass = PIt->second;
+            auto NIt = QueryParams.find("name");
+            if (NIt != QueryParams.end()) FName = NIt->second;
+            auto TIt = QueryParams.find("type");
+            if (TIt != QueryParams.end())
+              StringRef(TIt->second).getAsInteger(10, FType);
+            Res = handleGetSourceRemarks(
+                Client, resolveSnapshotHTTP(Client, SnapIt->second),
+                PathIt->second, FPass, FName, FType);
+          }
+        } else if (Path == "/api/v1/source") {
+          auto PathIt = QueryParams.find("path");
+          auto SnapIt = QueryParams.find("snapshot_id");
+          if (PathIt == QueryParams.end() || SnapIt == QueryParams.end())
+            Res = makeJSONErrorStr(400, "path and snapshot_id required");
+          else
+            Res = handleGetSource(
+                Client, resolveSnapshotHTTP(Client, SnapIt->second),
+                PathIt->second);
         } else if (Path == "/api/v1/jobs")
           Res = handleGetJobs(Client);
         else if (IsAPI && Segs.size() == 4 && Segs[2] == "jobs")

>From c15fddbbf73e275151746b504a51f7da28db01b6 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 24 Jun 2026 17:53:53 +0530
Subject: [PATCH 23/41] [llvm-advisor] add remarks diff engine with
 function-level and remark-level comparison

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/HTTPServer.cpp            | 289 ++++++++++++++++++
 1 file changed, 289 insertions(+)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index be6cf851d9f09..852b886190227 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1131,6 +1131,278 @@ static HTTPResult handleGetCompareCapability(CoreClient &Client,
   return makeJSONSuccess(200, Client.compareCapability(Before, After, CapID));
 }
 
+struct FuncProfile {
+  int64_t Total = 0, Missed = 0, Passed = 0, Analysis = 0, HotnessSum = 0;
+};
+
+static void buildFuncProfiles(CoreClient &Client, StringRef SnapID,
+                              StringMap<FuncProfile> &Out) {
+  const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
+  SmallVector<UnitRecord, 64> Units =
+      Client.storage().metadata().listUnits(SnapID);
+  for (const UnitRecord &U : Units) {
+    Expected<json::Array> Results = Client.queryUnit(U.ID, Caps);
+    if (!Results) { consumeError(Results.takeError()); continue; }
+    for (const json::Value &RV : *Results) {
+      const json::Object *RO = RV.getAsObject();
+      if (!RO || RO->getString("capability").value_or("") != "llvm.remarks.relational")
+        continue;
+      const json::Object *VO = RO->getObject("value");
+      if (!VO) continue;
+      const json::Object *Cols = VO->getObject("columns");
+      const json::Object *Strs = VO->getObject("strings");
+      if (!Cols || !Strs) continue;
+      const json::Array *TypeCol = Cols->getArray("type");
+      const json::Array *FuncCol = Cols->getArray("function");
+      const json::Array *HotnessCol = Cols->getArray("hotness");
+      const json::Array *FuncStrs = Strs->getArray("function");
+      if (!TypeCol || !FuncCol || !HotnessCol || !FuncStrs) continue;
+      size_t N = TypeCol->size();
+      for (size_t I = 0; I < N; ++I) {
+        int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+        if (FI < 0 || FI >= (int64_t)FuncStrs->size()) continue;
+        StringRef Func = (*FuncStrs)[FI].getAsString().value_or("");
+        if (Func.empty()) continue;
+        int64_t T = (*TypeCol)[I].getAsInteger().value_or(0);
+        int64_t H = (*HotnessCol)[I].getAsInteger().value_or(0);
+        FuncProfile &P = Out[Func];
+        P.Total++;
+        if (T == 1) P.Passed++;
+        else if (T == 2) P.Missed++;
+        else if (T == 3) P.Analysis++;
+        if (H > 0) P.HotnessSum += H;
+      }
+    }
+  }
+}
+
+static HTTPResult handleGetCompareRemarks(CoreClient &Client,
+                                          StringRef Before, StringRef After,
+                                          int64_t Offset, int64_t Limit) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
+
+  StringMap<FuncProfile> BeforeProf, AfterProf;
+  buildFuncProfiles(Client, Before, BeforeProf);
+  buildFuncProfiles(Client, After, AfterProf);
+
+  struct FuncDiff {
+    StringRef Name;
+    FuncProfile Before, After;
+    int64_t DeltaMissed;
+    int64_t DeltaTotal;
+  };
+
+  SmallVector<FuncDiff, 256> Diffs;
+  StringSet<> Seen;
+
+  for (auto &KV : AfterProf) {
+    Seen.insert(KV.first());
+    FuncProfile B = BeforeProf.lookup(KV.first());
+    FuncDiff D;
+    D.Name = KV.first();
+    D.Before = B;
+    D.After = KV.second;
+    D.DeltaMissed = KV.second.Missed - B.Missed;
+    D.DeltaTotal = KV.second.Total - B.Total;
+    if (D.DeltaMissed != 0 || D.DeltaTotal != 0 || B.Total == 0)
+      Diffs.push_back(D);
+  }
+  for (auto &KV : BeforeProf) {
+    if (Seen.contains(KV.first())) continue;
+    FuncDiff D;
+    D.Name = KV.first();
+    D.Before = KV.second;
+    D.DeltaMissed = -KV.second.Missed;
+    D.DeltaTotal = -KV.second.Total;
+    Diffs.push_back(D);
+  }
+
+  llvm::sort(Diffs, [](const FuncDiff &A, const FuncDiff &B) {
+    return std::abs(A.DeltaMissed) > std::abs(B.DeltaMissed);
+  });
+
+  int64_t TotalChanged = Diffs.size();
+  int64_t Added = 0, Removed = 0, NewMissed = 0, ResolvedMissed = 0;
+  for (auto &D : Diffs) {
+    if (D.Before.Total == 0) Added++;
+    else if (D.After.Total == 0) Removed++;
+    if (D.DeltaMissed > 0) NewMissed += D.DeltaMissed;
+    else ResolvedMissed += -D.DeltaMissed;
+  }
+
+  if (Offset < 0) Offset = 0;
+  if (Limit <= 0) Limit = 100;
+
+  std::string Body;
+  raw_string_ostream OS(Body);
+  writeSuccessEnvelope(OS, [&](json::OStream &JOS) {
+    JOS.object([&] {
+      JOS.attribute("total", TotalChanged);
+      JOS.attribute("offset", Offset);
+      JOS.attribute("limit", Limit);
+      JOS.attributeBegin("summary");
+      JOS.object([&] {
+        JOS.attribute("functions_changed", TotalChanged);
+        JOS.attribute("functions_added", Added);
+        JOS.attribute("functions_removed", Removed);
+        JOS.attribute("new_missed", NewMissed);
+        JOS.attribute("resolved_missed", ResolvedMissed);
+      });
+      JOS.attributeEnd();
+      JOS.attributeBegin("functions");
+      JOS.arrayBegin();
+      int64_t End = std::min(Offset + Limit, TotalChanged);
+      for (int64_t I = Offset; I < End; ++I) {
+        auto &D = Diffs[I];
+        JOS.object([&] {
+          JOS.attribute("name", D.Name);
+          JOS.attributeBegin("before");
+          JOS.object([&] {
+            JOS.attribute("total", D.Before.Total);
+            JOS.attribute("missed", D.Before.Missed);
+            JOS.attribute("passed", D.Before.Passed);
+            JOS.attribute("analysis", D.Before.Analysis);
+            JOS.attribute("hotness_sum", D.Before.HotnessSum);
+          });
+          JOS.attributeEnd();
+          JOS.attributeBegin("after");
+          JOS.object([&] {
+            JOS.attribute("total", D.After.Total);
+            JOS.attribute("missed", D.After.Missed);
+            JOS.attribute("passed", D.After.Passed);
+            JOS.attribute("analysis", D.After.Analysis);
+            JOS.attribute("hotness_sum", D.After.HotnessSum);
+          });
+          JOS.attributeEnd();
+          JOS.attribute("delta_missed", D.DeltaMissed);
+          JOS.attribute("delta_total", D.DeltaTotal);
+        });
+      }
+      JOS.arrayEnd();
+      JOS.attributeEnd();
+    });
+  });
+  OS.flush();
+  return HTTPResult{200, "application/json", std::move(Body)};
+}
+
+static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
+                                                 StringRef Before,
+                                                 StringRef After,
+                                                 StringRef FuncName) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
+
+  struct Remark { std::string Pass, Name; int64_t Type, Line, Hotness; };
+
+  auto collectRemarks = [&](StringRef SnapID) {
+    std::vector<Remark> Out;
+    const SmallVector<std::string, 1> Caps{"llvm.remarks.relational"};
+    SmallVector<UnitRecord, 64> Units =
+        Client.storage().metadata().listUnits(SnapID);
+    for (const UnitRecord &U : Units) {
+      Expected<json::Array> Results = Client.queryUnit(U.ID, Caps);
+      if (!Results) { consumeError(Results.takeError()); continue; }
+      for (const json::Value &RV : *Results) {
+        const json::Object *RO = RV.getAsObject();
+        if (!RO || RO->getString("capability").value_or("") != "llvm.remarks.relational")
+          continue;
+        const json::Object *VO = RO->getObject("value");
+        if (!VO) continue;
+        const json::Object *Cols = VO->getObject("columns");
+        const json::Object *Strs = VO->getObject("strings");
+        if (!Cols || !Strs) continue;
+        const json::Array *FuncCol = Cols->getArray("function");
+        const json::Array *FuncStrs = Strs->getArray("function");
+        const json::Array *PassCol = Cols->getArray("pass");
+        const json::Array *NameCol = Cols->getArray("name");
+        const json::Array *TypeCol = Cols->getArray("type");
+        const json::Array *LineCol = Cols->getArray("line");
+        const json::Array *HotnessCol = Cols->getArray("hotness");
+        const json::Array *PassStrs = Strs->getArray("pass");
+        const json::Array *NameStrs = Strs->getArray("name");
+        if (!FuncCol || !FuncStrs || !PassCol || !NameCol || !TypeCol ||
+            !LineCol || !HotnessCol || !PassStrs || !NameStrs) continue;
+        size_t N = FuncCol->size();
+        for (size_t I = 0; I < N; ++I) {
+          int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+          if (FI < 0 || FI >= (int64_t)FuncStrs->size()) continue;
+          if ((*FuncStrs)[FI].getAsString().value_or("") != FuncName) continue;
+          int64_t PI = (*PassCol)[I].getAsInteger().value_or(-1);
+          int64_t NI = (*NameCol)[I].getAsInteger().value_or(-1);
+          Remark R;
+          R.Pass = PI >= 0 && PI < (int64_t)PassStrs->size()
+              ? (*PassStrs)[PI].getAsString().value_or("").str() : "";
+          R.Name = NI >= 0 && NI < (int64_t)NameStrs->size()
+              ? (*NameStrs)[NI].getAsString().value_or("").str() : "";
+          R.Type = (*TypeCol)[I].getAsInteger().value_or(-1);
+          R.Line = (*LineCol)[I].getAsInteger().value_or(-1);
+          R.Hotness = (*HotnessCol)[I].getAsInteger().value_or(-1);
+          Out.push_back(std::move(R));
+        }
+      }
+    }
+    return Out;
+  };
+
+  std::vector<Remark> BeforeRems = collectRemarks(Before);
+  std::vector<Remark> AfterRems = collectRemarks(After);
+
+  // Match by (pass, name, type) — group and count
+  struct Key { std::string Pass, Name; int64_t Type; };
+  auto makeKey = [](const Remark &R) { return R.Pass + "\0" + R.Name + "\0" + std::to_string(R.Type); };
+
+  StringMap<int64_t> BeforeCounts, AfterCounts;
+  for (auto &R : BeforeRems) BeforeCounts[makeKey(R)]++;
+  for (auto &R : AfterRems) AfterCounts[makeKey(R)]++;
+
+  json::Array Added, Removed;
+  StringSet<> AllKeys;
+  for (auto &KV : AfterCounts) AllKeys.insert(KV.first());
+  for (auto &KV : BeforeCounts) AllKeys.insert(KV.first());
+
+  for (auto &K : AllKeys) {
+    int64_t B = BeforeCounts.lookup(K.getKey());
+    int64_t A = AfterCounts.lookup(K.getKey());
+    if (A > B) {
+      // Parse key back
+      StringRef S = K.getKey();
+      auto [PassName, Rest] = S.split('\0');
+      auto [Name, TypeStr] = Rest.split('\0');
+      int64_t Type = 0; TypeStr.getAsInteger(10, Type);
+      for (int64_t I = 0; I < A - B; ++I)
+        Added.push_back(json::Object{{"pass", PassName}, {"name", Name}, {"type", Type}, {"count", A - B}});
+      // Only push once
+      break;
+    }
+  }
+  // Rebuild properly
+  Added.clear();
+  Removed.clear();
+  for (auto &K : AllKeys) {
+    int64_t B = BeforeCounts.lookup(K.getKey());
+    int64_t A = AfterCounts.lookup(K.getKey());
+    if (A == B) continue;
+    StringRef S = K.getKey();
+    auto [Pass, Rest] = S.split('\0');
+    auto [Name, TypeStr] = Rest.split('\0');
+    int64_t Type = 0; TypeStr.getAsInteger(10, Type);
+    json::Object Entry;
+    Entry["pass"] = Pass; Entry["name"] = Name; Entry["type"] = Type;
+    Entry["before_count"] = B; Entry["after_count"] = A;
+    Entry["delta"] = A - B;
+    if (A > B) Added.push_back(std::move(Entry));
+    else Removed.push_back(std::move(Entry));
+  }
+
+  json::Object Result;
+  Result["function"] = FuncName.str();
+  Result["before_total"] = static_cast<int64_t>(BeforeRems.size());
+  Result["after_total"] = static_cast<int64_t>(AfterRems.size());
+  Result["added"] = std::move(Added);
+  Result["removed"] = std::move(Removed);
+  return makeJSONSuccess(200, std::move(Result));
+}
+
 static HTTPResult handleInspect(CoreClient &Client, StringRef Mode,
                                 StringRef Body) {
   Expected<json::Value> Parsed = json::parse(Body);
@@ -1428,6 +1700,23 @@ Error llvm::advisor::HTTPServer::run() {
           Res = handleGetCompareCapability(Client, resolveSnapshotHTTP(Client, urlDecode(Segs[3])),
                                            resolveSnapshotHTTP(Client, urlDecode(Segs[4])),
                                            urlDecode(Segs[6]));
+        else if (IsAPI && Segs.size() == 6 && Segs[2] == "compare" &&
+                 Segs[5] == "remarks") {
+          int64_t Off = 0, Lim = 100;
+          auto OIt = QueryParams.find("offset");
+          if (OIt != QueryParams.end()) StringRef(OIt->second).getAsInteger(10, Off);
+          auto LIt = QueryParams.find("limit");
+          if (LIt != QueryParams.end()) StringRef(LIt->second).getAsInteger(10, Lim);
+          Res = handleGetCompareRemarks(Client,
+              resolveSnapshotHTTP(Client, urlDecode(Segs[3])),
+              resolveSnapshotHTTP(Client, urlDecode(Segs[4])), Off, Lim);
+        }
+        else if (IsAPI && Segs.size() == 7 && Segs[2] == "compare" &&
+                 Segs[5] == "remarks")
+          Res = handleGetCompareFunctionDetail(Client,
+              resolveSnapshotHTTP(Client, urlDecode(Segs[3])),
+              resolveSnapshotHTTP(Client, urlDecode(Segs[4])),
+              urlDecode(Segs[6]));
         else if (!IsAPI)
           Res = {200, "text/html", Index};
       } else if (Method == "POST") {

>From b5624fd0ece28b648faa8350e27072e9ed44e9a4 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Tue, 30 Jun 2026 15:05:42 +0530
Subject: [PATCH 24/41] [llvm-advisor] add standalone remarks file import via
 CLI and HTTP

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/CLI/CLIHandler.cpp             | 32 ++++++++++
 .../llvm-advisor/src/Client/CoreClient.cpp    |  8 +++
 .../llvm-advisor/src/Client/CoreClient.h      |  4 ++
 .../src/Client/HTTP/HTTPServer.cpp            | 49 ++++++++++++++
 .../llvm-advisor/src/Core/CaptureCore.cpp     | 64 +++++++++++++++++++
 .../tools/llvm-advisor/src/Core/CaptureCore.h |  4 ++
 6 files changed, 161 insertions(+)

diff --git a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
index af4f9ee89c7a6..7e4f19c7947af 100644
--- a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
@@ -175,6 +175,8 @@ cl::SubCommand CapabilitiesCmd("capabilities", "List declared capabilities");
 cl::SubCommand InspectStorageCmd("inspect-storage", "Inspect storage state");
 cl::SubCommand MaintenanceCmd("maintenance-compact", "Compact CAS storage");
 cl::SubCommand ServeCmd("serve", "Run the embedded HTTP server");
+cl::SubCommand ImportCmd("import",
+                         "Create a snapshot from standalone remarks files");
 
 cl::opt<std::string> CaptureSourceRoot("source-root",
                                        cl::desc("Source root (default: auto)"),
@@ -186,6 +188,15 @@ cl::opt<std::string> CaptureBuildRoot(
 cl::opt<std::string> CaptureProfile("profile",
                                     cl::desc("Capture profile JSON path"),
                                     cl::init(""), cl::sub(CaptureCmd));
+
+cl::list<std::string> ImportFiles(cl::Positional, cl::desc("<remark files>"),
+                                  cl::OneOrMore, cl::sub(ImportCmd));
+cl::opt<std::string> ImportSourceRoot("source-root",
+                                      cl::desc("Source root for path resolution"),
+                                      cl::init(""), cl::sub(ImportCmd));
+cl::list<std::string> ImportCapabilities(
+    "capability", cl::desc("Capability to run (repeatable)"),
+    cl::ZeroOrMore, cl::sub(ImportCmd));
 cl::list<std::string> CaptureCapabilities(
     "capability",
     cl::desc("Capability ID; may be repeated; overrides --profile"),
@@ -684,6 +695,27 @@ int CLIHandler::run(int argc, char **argv) {
   }
 
 
+  if (ImportCmd) {
+    SmallVector<std::string, 8> Paths(ImportFiles.begin(), ImportFiles.end());
+    SmallVector<std::string, 4> Caps(ImportCapabilities.begin(),
+                                     ImportCapabilities.end());
+    std::string SrcRoot = ImportSourceRoot.getValue();
+    if (SrcRoot.empty()) {
+      SmallString<256> CWD;
+      sys::fs::current_path(CWD);
+      SrcRoot = CWD.str().str();
+    }
+    Expected<SnapshotRecord> Snap =
+        (*Client)->importRemarks(Paths, SrcRoot, Caps);
+    if (!Snap)
+      return printError(Snap.takeError());
+    outs() << formatv("Snapshot {0} created — {1} file(s)\n",
+                      Snap->ID.substr(0, 8),
+                      Paths.size());
+    outs() << formatv("  Full ID: {0}\n", Snap->ID);
+    return 0;
+  }
+
   if (ServeCmd) {
     outs() << formatv("Starting HTTP server on port {0}...\n",
                       ServePort.getValue());
diff --git a/llvm/tools/llvm-advisor/src/Client/CoreClient.cpp b/llvm/tools/llvm-advisor/src/Client/CoreClient.cpp
index 57bcc804797e6..5effc5a1b566d 100644
--- a/llvm/tools/llvm-advisor/src/Client/CoreClient.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/CoreClient.cpp
@@ -319,6 +319,14 @@ CoreClient::createSnapshot(StringRef SourceRoot, StringRef BuildRoot,
   return Capture.createSnapshot(SourceRoot, BuildRoot, Capabilities);
 }
 
+Expected<SnapshotRecord>
+CoreClient::importRemarks(ArrayRef<std::string> RemarkPaths,
+                          StringRef SourceRoot,
+                          ArrayRef<std::string> Capabilities) {
+  CaptureCore Capture(*Storage, Registry);
+  return Capture.importRemarks(RemarkPaths, SourceRoot, Capabilities);
+}
+
 SmallVector<SnapshotRecord, 16> CoreClient::listSnapshots() const {
   SnapshotManager Manager(*Storage);
   return Manager.list();
diff --git a/llvm/tools/llvm-advisor/src/Client/CoreClient.h b/llvm/tools/llvm-advisor/src/Client/CoreClient.h
index a19881aa3d762..e5fccd938854a 100644
--- a/llvm/tools/llvm-advisor/src/Client/CoreClient.h
+++ b/llvm/tools/llvm-advisor/src/Client/CoreClient.h
@@ -38,6 +38,9 @@ class CoreClient {
   Expected<SnapshotRecord> createSnapshot(StringRef SourceRoot,
                                           StringRef BuildRoot,
                                           ArrayRef<std::string> Capabilities);
+  Expected<SnapshotRecord> importRemarks(ArrayRef<std::string> RemarkPaths,
+                                         StringRef SourceRoot,
+                                         ArrayRef<std::string> Capabilities);
   SmallVector<SnapshotRecord, 16> listSnapshots() const;
   SmallVector<UnitRecord, 64> listUnits(StringRef SnapshotID) const;
   SmallVector<CapabilitySpec, 32> listCapabilities() const;
@@ -67,6 +70,7 @@ class CoreClient {
   json::Value inspectStorage() const;
   Error compactStorage();
   StorageManager &storage() { return *Storage; }
+  CapabilityRegistry &registry() { return Registry; }
 
 private:
   explicit CoreClient(std::unique_ptr<StorageManager> Storage);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 852b886190227..30239d095c507 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -14,6 +14,7 @@
 #include "Analysis/IR/RemarksRelationalSchema.h"
 #include "Client/HTTP/HTTPServer.h"
 #include "Client/HTTP/Handlers/StaticHandler.h"
+#include "Utils/Hashing.h"
 #include "Utils/JSON.h"
 #include "Utils/Normalization.h"
 
@@ -1403,6 +1404,52 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
   return makeJSONSuccess(200, std::move(Result));
 }
 
+static HTTPResult handlePostImport(CoreClient &Client, StringRef Body,
+                                   const StringMap<std::string> &Params) {
+  std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
+
+  if (Body.empty())
+    return makeJSONErrorStr(400, "request body is empty");
+
+  auto FilenameIt = Params.find("filename");
+  std::string Filename =
+      FilenameIt != Params.end() ? FilenameIt->second : "remarks.opt.yaml";
+
+  auto SourceRootIt = Params.find("source_root");
+  std::string SourceRoot =
+      SourceRootIt != Params.end() ? SourceRootIt->second : "";
+
+  SmallString<256> ArtDir(Client.storage().root());
+  sys::path::append(ArtDir, "artifacts");
+  std::string ContentHash = hashString(Body);
+  sys::path::append(ArtDir, ContentHash);
+  sys::fs::create_directories(ArtDir);
+
+  SmallString<256> FilePath(ArtDir);
+  sys::path::append(FilePath, Filename);
+  {
+    std::error_code EC;
+    raw_fd_ostream Out(FilePath, EC);
+    if (EC)
+      return makeJSONErrorStr(500, "failed to write uploaded file");
+    Out << Body;
+  }
+
+  SmallVector<std::string, 1> Paths = {std::string(FilePath)};
+  SmallVector<std::string, 2> Caps = {"llvm.remarks.relational",
+                                      "llvm.remarks.summary"};
+  Expected<SnapshotRecord> Snap =
+      Client.importRemarks(Paths, SourceRoot, Caps);
+  if (!Snap)
+    return makeJSONError(500, Snap.takeError());
+
+  json::Object Result;
+  Result["snapshot_id"] = Snap->ID;
+  Result["units"] = 1;
+  Result["filename"] = Filename;
+  return makeJSONSuccess(201, std::move(Result));
+}
+
 static HTTPResult handleInspect(CoreClient &Client, StringRef Mode,
                                 StringRef Body) {
   Expected<json::Value> Parsed = json::parse(Body);
@@ -1722,6 +1769,8 @@ Error llvm::advisor::HTTPServer::run() {
       } else if (Method == "POST") {
         if (IsAPI && Segs.size() == 4 && Segs[2] == "inspect")
           Res = handleInspect(Client, Segs[3], Req.Body);
+        else if (IsAPI && Segs.size() == 3 && Segs[2] == "import")
+          Res = handlePostImport(Client, Req.Body, QueryParams);
         else
           Res = makeJSONErrorStr(405, "unsupported POST route");
       } else if (Method == "OPTIONS") {
diff --git a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
index 5f48a94ac9034..404271d442c2b 100644
--- a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
+++ b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
@@ -269,3 +269,67 @@ CaptureCore::createSnapshot(StringRef SourceRoot, StringRef BuildRoot,
 
   return *Snapshot;
 }
+
+Expected<SnapshotRecord>
+CaptureCore::importRemarks(ArrayRef<std::string> RemarkPaths,
+                           StringRef SourceRoot,
+                           ArrayRef<std::string> Capabilities) {
+  uint64_t Now = std::chrono::duration_cast<std::chrono::seconds>(
+                     std::chrono::system_clock::now().time_since_epoch())
+                     .count();
+
+  SnapshotRecord Snapshot;
+  Snapshot.SourceRoot = SourceRoot.str();
+  Snapshot.CreatedUnix = Now;
+  Snapshot.ID = computeSnapshotID(SourceRoot, "imported", Now);
+  if (Error Err = Storage.metadata().putSnapshot(Snapshot))
+    return std::move(Err);
+
+  SmallVector<std::string, 8> DefaultCaps = {"llvm.remarks.relational",
+                                             "llvm.remarks.summary"};
+  ArrayRef<std::string> CapsToRun =
+      Capabilities.empty() ? ArrayRef<std::string>(DefaultCaps) : Capabilities;
+
+  CapabilityPlanner Planner(Registry);
+  Expected<SmallVector<CapabilityNode, 16>> Plan = Planner.plan(CapsToRun);
+  if (!Plan)
+    return Plan.takeError();
+  CapabilityScheduler Scheduler;
+  SmallVector<CapabilityNode, 16> Schedule = Scheduler.schedule(*Plan);
+  CapabilityExecutor Executor(Registry, Storage);
+
+  for (const std::string &Path : RemarkPaths) {
+    if (!sys::fs::exists(Path))
+      continue;
+
+    Expected<std::string> ContentHash = hashFile(Path);
+    if (!ContentHash) {
+      consumeError(ContentHash.takeError());
+      continue;
+    }
+
+    StringRef FileName = sys::path::filename(Path);
+    std::string Stem = sys::path::stem(FileName).str();
+
+    UnitRecord Unit;
+    Unit.SnapshotID = Snapshot.ID;
+    Unit.RemarksPath = Path;
+    Unit.SourcePath = Stem;
+    Unit.Language = "unknown";
+    Unit.SourceContentHash = *ContentHash;
+    Unit.CommandFingerprint = hashString("standalone-import");
+    Unit.ID = hashString(Path + "\0" + *ContentHash);
+
+    if (Error Err = Storage.metadata().putUnit(Unit))
+      return std::move(Err);
+
+    CapabilityContext Context = makeContext(Unit);
+    Expected<json::Array> Results = Executor.execute(Schedule, Context);
+    if (!Results) {
+      consumeError(Results.takeError());
+      continue;
+    }
+  }
+
+  return Snapshot;
+}
diff --git a/llvm/tools/llvm-advisor/src/Core/CaptureCore.h b/llvm/tools/llvm-advisor/src/Core/CaptureCore.h
index 4f75f5e605ca8..5196463c3999a 100644
--- a/llvm/tools/llvm-advisor/src/Core/CaptureCore.h
+++ b/llvm/tools/llvm-advisor/src/Core/CaptureCore.h
@@ -30,6 +30,10 @@ class CaptureCore {
                                           StringRef BuildRoot,
                                           ArrayRef<std::string> Capabilities);
 
+  Expected<SnapshotRecord> importRemarks(ArrayRef<std::string> RemarkPaths,
+                                         StringRef SourceRoot,
+                                         ArrayRef<std::string> Capabilities);
+
 private:
   Expected<SnapshotRecord> initializeSnapshot(StringRef SourceRoot,
                                                StringRef BuildRoot);

>From dfcd65a2641ba1ce558a7f0867976f599fc60844 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Fri, 3 Jul 2026 12:07:19 +0530
Subject: [PATCH 25/41] [llvm-advisor] add browser upload UI for standalone
 remarks import

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 108 +++++++++++++++++-
 .../src/Client/HTTP/Assets/core.js            |  17 +++
 .../src/Client/HTTP/Assets/index_html.inc     | 108 +++++++++++++++++-
 .../src/Client/HTTP/Assets/shell.js           |  88 +++++++++++++-
 .../src/Client/HTTP/Assets/styles.css         |   3 +
 5 files changed, 321 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 31cdb1c7cd329..05120ae87a7b8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -263,6 +263,9 @@
 /* Command Palette */
 .cmd-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:20vh}
 .cmd-overlay.open{display:flex}
+.import-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:18vh}
+.import-overlay.open{display:flex}
+.import-panel{width:440px;background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:18px;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-box{width:480px;background:var(--bg);border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-input{width:100%;padding:16px;font-family:var(--mono);font-size:14px;background:transparent;border-bottom:1px solid var(--border)}
 .cmd-results{max-height:300px;overflow-y:auto}
@@ -864,6 +867,22 @@
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
+  async importFile(file, sourceRoot) {
+    let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
+    if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
+    try {
+      const r = await fetch(url, {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/octet-stream' },
+        body: file,
+      });
+      const j = await r.json();
+      if (j.status === 'error') return { ok: false, error: j.error?.message || 'Import failed', data: null };
+      return { ok: true, data: j.data ?? j, error: null };
+    } catch (e) {
+      return { ok: false, error: e.message, data: null };
+    }
+  },
 };
 
 // --- State ---
@@ -881,6 +900,7 @@
     detailOpen: false,
     detailContent: null,
     commandPaletteOpen: false,
+    importModalOpen: false,
   },
   get(key) { return this._data[key]; },
   set(key, value) {
@@ -2028,6 +2048,7 @@
     );
     app.appendChild(wrap);
     app.appendChild(CommandPalette.render());
+    app.appendChild(this.importModal());
 
     // React to state
     State.on('sidebarPinned', v => app.classList.toggle('sb-exp', v));
@@ -2036,6 +2057,9 @@
       document.querySelector('.cmd-overlay')?.classList.toggle('open', v);
       if (v) document.querySelector('.cmd-input')?.focus();
     });
+    State.on('importModalOpen', v => {
+      document.querySelector('.import-overlay')?.classList.toggle('open', v);
+    });
     State.on('route', () => this.updateNav());
     State.on('health', h => this.updateStatus(h));
 
@@ -2067,7 +2091,10 @@
         h('div', { class: 'dropdown', id: 'snapshot-dropdown' },
           h('button', { class: 'dd-trigger', onClick: e => this.toggleDropdown(e) }, 'Snapshot ▾'),
           h('div', { class: 'dd-menu' })
-        )
+        ),
+        h('button', { class: 'dd-trigger', style: { marginLeft: '8px' },
+          title: 'Import a remarks file',
+          onClick: () => State.set('importModalOpen', true) }, '+ Import')
       ),
       h('div', { class: 'topbar-right' },
         h('div', { class: 'status-pill', id: 'status-pill' },
@@ -2083,6 +2110,85 @@
     );
   },
 
+  importModal() {
+    const close = () => State.set('importModalOpen', false);
+
+    const status = h('div', { class: 'import-status', style: { marginTop: '12px', fontSize: '12px', minHeight: '18px' } });
+    const fileInput = h('input', { type: 'file', accept: '.yaml,.bitstream,.opt', style: { display: 'none' } });
+
+    const doUpload = async (file) => {
+      if (!file) return;
+      status.textContent = `Uploading ${file.name} (${(file.size / 1024).toFixed(0)} KB)…`;
+      status.style.color = 'var(--text-muted)';
+      const res = await API.importFile(file);
+      if (!res.ok) {
+        status.textContent = `Error: ${res.error}`;
+        status.style.color = 'var(--red)';
+        return;
+      }
+      status.textContent = `Imported. Snapshot ${res.data.snapshot_id.slice(0, 8)} created.`;
+      status.style.color = 'var(--green)';
+      // Refresh snapshot list and navigate to the new snapshot
+      const snaps = await API.snapshots();
+      if (snaps.ok) {
+        const list = Array.isArray(snaps.data) ? snaps.data : [];
+        list.sort((a, b) => (b.created_unix || 0) - (a.created_unix || 0));
+        State.set('snapshots', list);
+        const newSnap = list.find(s => s.id === res.data.snapshot_id);
+        if (newSnap) {
+          State.set('currentSnapshot', newSnap);
+          this.updateSelectors();
+        }
+      }
+      setTimeout(() => { close(); Router.navigate('/'); }, 900);
+    };
+
+    const dropZone = h('div', {
+      class: 'import-dropzone',
+      style: {
+        border: '2px dashed var(--border)', borderRadius: '8px', padding: '32px',
+        textAlign: 'center', cursor: 'pointer', color: 'var(--text-muted)',
+        transition: 'border-color 0.15s, background 0.15s',
+      },
+      onClick: () => fileInput.click(),
+    },
+      h('div', { style: { fontSize: '13px', marginBottom: '4px' } }, 'Drop a remarks file here'),
+      h('div', { style: { fontSize: '11px' } }, 'or click to browse (.yaml, .bitstream)')
+    );
+
+    dropZone.addEventListener('dragover', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--accent)';
+      dropZone.style.background = 'var(--bg2)';
+    });
+    dropZone.addEventListener('dragleave', () => {
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+    });
+    dropZone.addEventListener('drop', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+      if (e.dataTransfer.files.length) doUpload(e.dataTransfer.files[0]);
+    });
+    fileInput.addEventListener('change', (e) => {
+      if (e.target.files.length) doUpload(e.target.files[0]);
+    });
+
+    const panel = h('div', { class: 'import-panel', onClick: e => e.stopPropagation() },
+      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' } },
+        h('h3', { style: { margin: '0' } }, 'Import Remarks File'),
+        h('button', { class: 'dd-trigger', onClick: close }, '✕')
+      ),
+      dropZone,
+      fileInput,
+      status
+    );
+
+    const overlay = h('div', { class: 'import-overlay', onClick: close }, panel);
+    return overlay;
+  },
+
   sidebar() {
     const items = [
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index 576a6664f7381..e540d2e4a4a99 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -132,6 +132,22 @@ const API = {
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
+  async importFile(file, sourceRoot) {
+    let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
+    if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
+    try {
+      const r = await fetch(url, {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/octet-stream' },
+        body: file,
+      });
+      const j = await r.json();
+      if (j.status === 'error') return { ok: false, error: j.error?.message || 'Import failed', data: null };
+      return { ok: true, data: j.data ?? j, error: null };
+    } catch (e) {
+      return { ok: false, error: e.message, data: null };
+    }
+  },
 };
 
 // --- State ---
@@ -149,6 +165,7 @@ const State = {
     detailOpen: false,
     detailContent: null,
     commandPaletteOpen: false,
+    importModalOpen: false,
   },
   get(key) { return this._data[key]; },
   set(key, value) {
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index b628429e876d9..005b5c3e2ac94 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -266,6 +266,9 @@ ul,ol{list-style:none}
 /* Command Palette */
 .cmd-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:20vh}
 .cmd-overlay.open{display:flex}
+.import-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:18vh}
+.import-overlay.open{display:flex}
+.import-panel{width:440px;background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:18px;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-box{width:480px;background:var(--bg);border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-input{width:100%;padding:16px;font-family:var(--mono);font-size:14px;background:transparent;border-bottom:1px solid var(--border)}
 .cmd-results{max-height:300px;overflow-y:auto}
@@ -867,6 +870,22 @@ const API = {
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
+  async importFile(file, sourceRoot) {
+    let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
+    if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
+    try {
+      const r = await fetch(url, {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/octet-stream' },
+        body: file,
+      });
+      const j = await r.json();
+      if (j.status === 'error') return { ok: false, error: j.error?.message || 'Import failed', data: null };
+      return { ok: true, data: j.data ?? j, error: null };
+    } catch (e) {
+      return { ok: false, error: e.message, data: null };
+    }
+  },
 };
 
 // --- State ---
@@ -884,6 +903,7 @@ const State = {
     detailOpen: false,
     detailContent: null,
     commandPaletteOpen: false,
+    importModalOpen: false,
   },
   get(key) { return this._data[key]; },
   set(key, value) {
@@ -2031,6 +2051,7 @@ const Shell = {
     );
     app.appendChild(wrap);
     app.appendChild(CommandPalette.render());
+    app.appendChild(this.importModal());
 
     // React to state
     State.on('sidebarPinned', v => app.classList.toggle('sb-exp', v));
@@ -2039,6 +2060,9 @@ const Shell = {
       document.querySelector('.cmd-overlay')?.classList.toggle('open', v);
       if (v) document.querySelector('.cmd-input')?.focus();
     });
+    State.on('importModalOpen', v => {
+      document.querySelector('.import-overlay')?.classList.toggle('open', v);
+    });
     State.on('route', () => this.updateNav());
     State.on('health', h => this.updateStatus(h));
 
@@ -2070,7 +2094,10 @@ const Shell = {
         h('div', { class: 'dropdown', id: 'snapshot-dropdown' },
           h('button', { class: 'dd-trigger', onClick: e => this.toggleDropdown(e) }, 'Snapshot ▾'),
           h('div', { class: 'dd-menu' })
-        )
+        ),
+        h('button', { class: 'dd-trigger', style: { marginLeft: '8px' },
+          title: 'Import a remarks file',
+          onClick: () => State.set('importModalOpen', true) }, '+ Import')
       ),
       h('div', { class: 'topbar-right' },
         h('div', { class: 'status-pill', id: 'status-pill' },
@@ -2086,6 +2113,85 @@ const Shell = {
     );
   },
 
+  importModal() {
+    const close = () => State.set('importModalOpen', false);
+
+    const status = h('div', { class: 'import-status', style: { marginTop: '12px', fontSize: '12px', minHeight: '18px' } });
+    const fileInput = h('input', { type: 'file', accept: '.yaml,.bitstream,.opt', style: { display: 'none' } });
+
+    const doUpload = async (file) => {
+      if (!file) return;
+      status.textContent = `Uploading ${file.name} (${(file.size / 1024).toFixed(0)} KB)…`;
+      status.style.color = 'var(--text-muted)';
+      const res = await API.importFile(file);
+      if (!res.ok) {
+        status.textContent = `Error: ${res.error}`;
+        status.style.color = 'var(--red)';
+        return;
+      }
+      status.textContent = `Imported. Snapshot ${res.data.snapshot_id.slice(0, 8)} created.`;
+      status.style.color = 'var(--green)';
+      // Refresh snapshot list and navigate to the new snapshot
+      const snaps = await API.snapshots();
+      if (snaps.ok) {
+        const list = Array.isArray(snaps.data) ? snaps.data : [];
+        list.sort((a, b) => (b.created_unix || 0) - (a.created_unix || 0));
+        State.set('snapshots', list);
+        const newSnap = list.find(s => s.id === res.data.snapshot_id);
+        if (newSnap) {
+          State.set('currentSnapshot', newSnap);
+          this.updateSelectors();
+        }
+      }
+      setTimeout(() => { close(); Router.navigate('/'); }, 900);
+    };
+
+    const dropZone = h('div', {
+      class: 'import-dropzone',
+      style: {
+        border: '2px dashed var(--border)', borderRadius: '8px', padding: '32px',
+        textAlign: 'center', cursor: 'pointer', color: 'var(--text-muted)',
+        transition: 'border-color 0.15s, background 0.15s',
+      },
+      onClick: () => fileInput.click(),
+    },
+      h('div', { style: { fontSize: '13px', marginBottom: '4px' } }, 'Drop a remarks file here'),
+      h('div', { style: { fontSize: '11px' } }, 'or click to browse (.yaml, .bitstream)')
+    );
+
+    dropZone.addEventListener('dragover', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--accent)';
+      dropZone.style.background = 'var(--bg2)';
+    });
+    dropZone.addEventListener('dragleave', () => {
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+    });
+    dropZone.addEventListener('drop', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+      if (e.dataTransfer.files.length) doUpload(e.dataTransfer.files[0]);
+    });
+    fileInput.addEventListener('change', (e) => {
+      if (e.target.files.length) doUpload(e.target.files[0]);
+    });
+
+    const panel = h('div', { class: 'import-panel', onClick: e => e.stopPropagation() },
+      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' } },
+        h('h3', { style: { margin: '0' } }, 'Import Remarks File'),
+        h('button', { class: 'dd-trigger', onClick: close }, '✕')
+      ),
+      dropZone,
+      fileInput,
+      status
+    );
+
+    const overlay = h('div', { class: 'import-overlay', onClick: close }, panel);
+    return overlay;
+  },
+
   sidebar() {
     const items = [
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
index 66421ab7db490..8718fdc868701 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
@@ -15,6 +15,7 @@ const Shell = {
     );
     app.appendChild(wrap);
     app.appendChild(CommandPalette.render());
+    app.appendChild(this.importModal());
 
     // React to state
     State.on('sidebarPinned', v => app.classList.toggle('sb-exp', v));
@@ -23,6 +24,9 @@ const Shell = {
       document.querySelector('.cmd-overlay')?.classList.toggle('open', v);
       if (v) document.querySelector('.cmd-input')?.focus();
     });
+    State.on('importModalOpen', v => {
+      document.querySelector('.import-overlay')?.classList.toggle('open', v);
+    });
     State.on('route', () => this.updateNav());
     State.on('health', h => this.updateStatus(h));
 
@@ -54,7 +58,10 @@ const Shell = {
         h('div', { class: 'dropdown', id: 'snapshot-dropdown' },
           h('button', { class: 'dd-trigger', onClick: e => this.toggleDropdown(e) }, 'Snapshot ▾'),
           h('div', { class: 'dd-menu' })
-        )
+        ),
+        h('button', { class: 'dd-trigger', style: { marginLeft: '8px' },
+          title: 'Import a remarks file',
+          onClick: () => State.set('importModalOpen', true) }, '+ Import')
       ),
       h('div', { class: 'topbar-right' },
         h('div', { class: 'status-pill', id: 'status-pill' },
@@ -70,6 +77,85 @@ const Shell = {
     );
   },
 
+  importModal() {
+    const close = () => State.set('importModalOpen', false);
+
+    const status = h('div', { class: 'import-status', style: { marginTop: '12px', fontSize: '12px', minHeight: '18px' } });
+    const fileInput = h('input', { type: 'file', accept: '.yaml,.bitstream,.opt', style: { display: 'none' } });
+
+    const doUpload = async (file) => {
+      if (!file) return;
+      status.textContent = `Uploading ${file.name} (${(file.size / 1024).toFixed(0)} KB)…`;
+      status.style.color = 'var(--text-muted)';
+      const res = await API.importFile(file);
+      if (!res.ok) {
+        status.textContent = `Error: ${res.error}`;
+        status.style.color = 'var(--red)';
+        return;
+      }
+      status.textContent = `Imported. Snapshot ${res.data.snapshot_id.slice(0, 8)} created.`;
+      status.style.color = 'var(--green)';
+      // Refresh snapshot list and navigate to the new snapshot
+      const snaps = await API.snapshots();
+      if (snaps.ok) {
+        const list = Array.isArray(snaps.data) ? snaps.data : [];
+        list.sort((a, b) => (b.created_unix || 0) - (a.created_unix || 0));
+        State.set('snapshots', list);
+        const newSnap = list.find(s => s.id === res.data.snapshot_id);
+        if (newSnap) {
+          State.set('currentSnapshot', newSnap);
+          this.updateSelectors();
+        }
+      }
+      setTimeout(() => { close(); Router.navigate('/'); }, 900);
+    };
+
+    const dropZone = h('div', {
+      class: 'import-dropzone',
+      style: {
+        border: '2px dashed var(--border)', borderRadius: '8px', padding: '32px',
+        textAlign: 'center', cursor: 'pointer', color: 'var(--text-muted)',
+        transition: 'border-color 0.15s, background 0.15s',
+      },
+      onClick: () => fileInput.click(),
+    },
+      h('div', { style: { fontSize: '13px', marginBottom: '4px' } }, 'Drop a remarks file here'),
+      h('div', { style: { fontSize: '11px' } }, 'or click to browse (.yaml, .bitstream)')
+    );
+
+    dropZone.addEventListener('dragover', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--accent)';
+      dropZone.style.background = 'var(--bg2)';
+    });
+    dropZone.addEventListener('dragleave', () => {
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+    });
+    dropZone.addEventListener('drop', (e) => {
+      e.preventDefault();
+      dropZone.style.borderColor = 'var(--border)';
+      dropZone.style.background = '';
+      if (e.dataTransfer.files.length) doUpload(e.dataTransfer.files[0]);
+    });
+    fileInput.addEventListener('change', (e) => {
+      if (e.target.files.length) doUpload(e.target.files[0]);
+    });
+
+    const panel = h('div', { class: 'import-panel', onClick: e => e.stopPropagation() },
+      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' } },
+        h('h3', { style: { margin: '0' } }, 'Import Remarks File'),
+        h('button', { class: 'dd-trigger', onClick: close }, '✕')
+      ),
+      dropZone,
+      fileInput,
+      status
+    );
+
+    const overlay = h('div', { class: 'import-overlay', onClick: close }, panel);
+    return overlay;
+  },
+
   sidebar() {
     const items = [
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
index 3359acac5eab5..57e78e075eda7 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
@@ -254,6 +254,9 @@ ul,ol{list-style:none}
 /* Command Palette */
 .cmd-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:20vh}
 .cmd-overlay.open{display:flex}
+.import-overlay{position:fixed;inset:0;background:rgba(0,0,0,.25);z-index:1000;display:none;align-items:flex-start;justify-content:center;padding-top:18vh}
+.import-overlay.open{display:flex}
+.import-panel{width:440px;background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:18px;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-box{width:480px;background:var(--bg);border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.12)}
 .cmd-input{width:100%;padding:16px;font-family:var(--mono);font-size:14px;background:transparent;border-bottom:1px solid var(--border)}
 .cmd-results{max-height:300px;overflow-y:auto}

>From 831098cf577fa82be376d38f23a2725a527cfd49 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Fri, 3 Jul 2026 17:51:59 +0530
Subject: [PATCH 26/41] [llvm-advisor] surface parse errors on remarks import
 instead of silent empty snapshot

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../llvm-advisor/src/Core/CaptureCore.cpp     | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
index 404271d442c2b..9186434b3f0da 100644
--- a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
+++ b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
@@ -9,6 +9,7 @@
 #include "Core/CaptureCore.h"
 #include "Analysis/AnalyzerBase.h"
 #include "Analysis/Clang/ClangAnalyzerUtils.h"
+#include "Analysis/RemarksAnalysisUtils.h"
 #include "Capability/CapabilityExecutor.h"
 #include "Capability/CapabilityPlanner.h"
 #include "Capability/CapabilityScheduler.h"
@@ -274,6 +275,34 @@ Expected<SnapshotRecord>
 CaptureCore::importRemarks(ArrayRef<std::string> RemarkPaths,
                            StringRef SourceRoot,
                            ArrayRef<std::string> Capabilities) {
+  if (RemarkPaths.empty())
+    return createStringError(inconvertibleErrorCode(),
+                             "no remark files provided");
+
+  // Pre-flight: validate each file is parseable before creating a snapshot.
+  // This surfaces version-mismatch / corruption errors to the user instead of
+  // silently producing an empty snapshot.
+  for (const std::string &Path : RemarkPaths) {
+    if (!sys::fs::exists(Path))
+      return createStringError(inconvertibleErrorCode(),
+                               Twine("remark file does not exist: ") + Path);
+    int64_t Seen = 0;
+    if (Error E = foreachRemark(Path, [&](const remarks::Remark &) -> Error {
+          ++Seen;
+          return Error::success();
+        }))
+      return joinErrors(
+          createStringError(inconvertibleErrorCode(),
+                            Twine("failed to parse remark file '") + Path +
+                                "': "),
+          std::move(E));
+    if (Seen == 0)
+      return createStringError(
+          inconvertibleErrorCode(),
+          Twine("remark file '") + Path +
+              "' contains no remarks (empty or unrecognized format)");
+  }
+
   uint64_t Now = std::chrono::duration_cast<std::chrono::seconds>(
                      std::chrono::system_clock::now().time_since_epoch())
                      .count();

>From 287dfa4c6a4692e860f7d6c07b0d0fab59c00f8a Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 5 Jul 2026 13:17:26 +0530
Subject: [PATCH 27/41] [llvm-advisor] add optimization diff UI to Compare tab

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 163 +++++++++++++++++-
 .../src/Client/HTTP/Assets/compare.js         | 159 ++++++++++++++++-
 .../src/Client/HTTP/Assets/core.js            |   2 +
 .../src/Client/HTTP/Assets/index_html.inc     | 163 +++++++++++++++++-
 .../src/Client/HTTP/Assets/styles.css         |   2 +
 5 files changed, 486 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 05120ae87a7b8..9fce6a0b97bf8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -512,6 +512,8 @@
 /* Compare Summary Section */
 .compare-summary-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
 .compare-summary-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);margin-bottom:14px}
+.compare-remarks-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
+.compare-remarks-section h3{font-size:13px;font-weight:600;margin-bottom:10px}
 .compare-health-delta{display:flex;align-items:center;gap:16px;padding:12px 0;margin-bottom:12px}
 .compare-health-value{font-family:var(--mono);font-size:28px;font-weight:700}
 .compare-health-arrow{font-size:18px}
@@ -865,6 +867,8 @@
     return API.get(url);
   },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
+  compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
+  compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
@@ -3580,6 +3584,9 @@
   _results: null,
   _baseSummary: null,
   _candidateSummary: null,
+  _remarksDiff: null,
+  _remarkPage: 0,
+  _remarkPageCount: 1,
 
   async render(params) {
     this._baseId = params.base || null;
@@ -3594,6 +3601,7 @@
 
     container.appendChild(h('div', { id: 'compare-summary-section' }));
     container.appendChild(h('div', { class: 'summary-bar', id: 'compare-summary' }));
+    container.appendChild(h('div', { id: 'compare-remarks-diff' }));
     container.appendChild(h('div', { class: 'section-header' }, 'Unit Changes'));
     container.appendChild(h('div', { id: 'compare-results' }));
 
@@ -3628,14 +3636,17 @@
     const sumSectionEl = document.getElementById('compare-summary-section');
     if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(h('div', { class: 'text-muted mono', style: { padding: '16px' } }, 'Comparing…')); }
 
-    const [compareRes, baseSumRes, candSumRes] = await Promise.all([
+    const [compareRes, baseSumRes, candSumRes, remDiffRes] = await Promise.all([
       API.compare(this._baseId, this._candidateId),
       API.snapshotSummary(this._baseId).catch(() => ({ ok: false, data: {} })),
       API.snapshotSummary(this._candidateId).catch(() => ({ ok: false, data: {} })),
+      API.compareRemarks(this._baseId, this._candidateId, 0, 100).catch(() => ({ ok: false, data: null })),
     ]);
 
     this._baseSummary = baseSumRes.ok && baseSumRes.data ? baseSumRes.data : {};
     this._candidateSummary = candSumRes.ok && candSumRes.data ? candSumRes.data : {};
+    this._remarksDiff = remDiffRes.ok && remDiffRes.data ? remDiffRes.data : null;
+    this._remarkPage = 0;
 
     if (!compareRes.ok) {
       if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(UI.errorCard(compareRes.error || 'Compare failed', () => this.runCompare())); }
@@ -3645,6 +3656,8 @@
     this._results = compareRes.data;
     this.renderMatchSummary(summaryEl);
     this.renderSummaryComparison(sumSectionEl);
+    const remDiffEl = document.getElementById('compare-remarks-diff');
+    if (remDiffEl) this.renderRemarksDiff(remDiffEl);
     this.renderResults(resultsEl);
   },
 
@@ -3750,6 +3763,154 @@
     el.appendChild(section);
   },
 
+  renderRemarksDiff(el) {
+    clearEl(el);
+    const diff = this._remarksDiff;
+    if (!diff) return;
+
+    const s = diff.summary || {};
+    const newMissed = s.new_missed || 0;
+    const resolved = s.resolved_missed || 0;
+    const changed = s.functions_changed || 0;
+    const added = s.functions_added || 0;
+    const removed = s.functions_removed || 0;
+
+    if (changed === 0 && newMissed === 0 && resolved === 0) return;
+
+    const section = h('div', { class: 'compare-remarks-section' });
+    section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
+
+    const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'New Missed'),
+        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+      ));
+    if (resolved > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Resolved'),
+        h('div', { class: 'values', style: { color: 'var(--green)' } }, `-${formatNumber(resolved)}`)
+      ));
+    impactBar.appendChild(h('div', { class: 'summary-metric' },
+      h('div', { class: 'label' }, 'Functions Changed'),
+      h('div', { class: 'values' }, formatNumber(changed))
+    ));
+    if (added > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Added'),
+        h('div', { class: 'values' }, formatNumber(added))
+      ));
+    if (removed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Removed'),
+        h('div', { class: 'values' }, formatNumber(removed))
+      ));
+    section.appendChild(impactBar);
+
+    const functions = diff.functions || [];
+    if (!functions.length) { el.appendChild(section); return; }
+
+    const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
+    const thead = h('tr', {},
+      h('th', {}, 'Function'),
+      h('th', { style: { textAlign: 'right' } }, 'Before'),
+      h('th', { style: { textAlign: 'right' } }, 'After'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+    );
+    tbl.appendChild(h('thead', {}, thead));
+    const tbody = h('tbody', {});
+
+    functions.forEach((fn, idx) => {
+      const delta = fn.delta_missed;
+      const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const row = h('tr', { style: { cursor: 'pointer' },
+        onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
+      },
+        h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
+        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
+        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
+        h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+      );
+      tbody.appendChild(row);
+    });
+    tbl.appendChild(tbody);
+
+    const wrap = h('div', { class: 'top-units-wrap', style: { maxHeight: '300px', overflow: 'auto' } }, tbl);
+    section.appendChild(wrap);
+
+    const total = diff.total || 0;
+    const pageSize = 100;
+    this._remarkPageCount = Math.max(1, Math.ceil(total / pageSize));
+    if (total > functions.length) {
+      const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+      const prevBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage <= 0) return;
+        this._remarkPage--;
+        await this._fetchRemarkPage(el);
+      }}, '← Prev');
+      const nextBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage >= this._remarkPageCount - 1) return;
+        this._remarkPage++;
+        await this._fetchRemarkPage(el);
+      }}, 'Next →');
+      const pageLabel = h('span', { class: 'text-muted' }, `Page ${this._remarkPage + 1} of ${this._remarkPageCount} (${formatNumber(total)} changed)`);
+      pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+      section.appendChild(pager);
+    }
+
+    el.appendChild(section);
+  },
+
+  async _fetchRemarkPage(el) {
+    const res = await API.compareRemarks(this._baseId, this._candidateId, this._remarkPage * 100, 100);
+    if (res.ok && res.data) { this._remarksDiff = res.data; this.renderRemarksDiff(el); }
+  },
+
+  async _toggleFnDetail(fn, row, tbody, idx) {
+    const existingId = `fn-detail-${idx}`;
+    const existing = tbody.querySelector(`#${existingId}`);
+    if (existing) { existing.remove(); row.classList.remove('expanded'); return; }
+    row.classList.add('expanded');
+    const detailRow = h('tr', { id: existingId });
+    const cell = h('td', { colspan: '5', style: { padding: '8px 12px', background: 'var(--bg2)', fontSize: '11px' } });
+    cell.textContent = 'Loading…';
+    detailRow.appendChild(cell);
+    row.after(detailRow);
+
+    const res = await API.compareFunctionDetail(this._baseId, this._candidateId, fn.name);
+    clearEl(cell);
+    if (!res.ok) { cell.textContent = 'Failed to load detail.'; return; }
+    const d = res.data;
+    const added = d.added || [];
+    const removed = d.removed || [];
+
+    if (!added.length && !removed.length) { cell.textContent = 'No remark-level changes found.'; return; }
+
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+
+    const makeEntries = (items, sign, color) => items.map(r =>
+      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+        h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
+        h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
+        h('span', { style: { fontWeight: '500' } }, r.name || ''),
+        h('span', { class: 'text-muted' }, r.pass || ''),
+        h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
+      )
+    );
+
+    if (removed.length) {
+      cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
+      makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
+    }
+    if (added.length) {
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+    }
+  },
+
   renderResults(el) {
     if (!el || !this._results) return;
     clearEl(el);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index 5a64e89f224a5..e66497a3fb055 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -8,6 +8,9 @@ const CompareView = {
   _results: null,
   _baseSummary: null,
   _candidateSummary: null,
+  _remarksDiff: null,
+  _remarkPage: 0,
+  _remarkPageCount: 1,
 
   async render(params) {
     this._baseId = params.base || null;
@@ -22,6 +25,7 @@ const CompareView = {
 
     container.appendChild(h('div', { id: 'compare-summary-section' }));
     container.appendChild(h('div', { class: 'summary-bar', id: 'compare-summary' }));
+    container.appendChild(h('div', { id: 'compare-remarks-diff' }));
     container.appendChild(h('div', { class: 'section-header' }, 'Unit Changes'));
     container.appendChild(h('div', { id: 'compare-results' }));
 
@@ -56,14 +60,17 @@ const CompareView = {
     const sumSectionEl = document.getElementById('compare-summary-section');
     if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(h('div', { class: 'text-muted mono', style: { padding: '16px' } }, 'Comparing…')); }
 
-    const [compareRes, baseSumRes, candSumRes] = await Promise.all([
+    const [compareRes, baseSumRes, candSumRes, remDiffRes] = await Promise.all([
       API.compare(this._baseId, this._candidateId),
       API.snapshotSummary(this._baseId).catch(() => ({ ok: false, data: {} })),
       API.snapshotSummary(this._candidateId).catch(() => ({ ok: false, data: {} })),
+      API.compareRemarks(this._baseId, this._candidateId, 0, 100).catch(() => ({ ok: false, data: null })),
     ]);
 
     this._baseSummary = baseSumRes.ok && baseSumRes.data ? baseSumRes.data : {};
     this._candidateSummary = candSumRes.ok && candSumRes.data ? candSumRes.data : {};
+    this._remarksDiff = remDiffRes.ok && remDiffRes.data ? remDiffRes.data : null;
+    this._remarkPage = 0;
 
     if (!compareRes.ok) {
       if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(UI.errorCard(compareRes.error || 'Compare failed', () => this.runCompare())); }
@@ -73,6 +80,8 @@ const CompareView = {
     this._results = compareRes.data;
     this.renderMatchSummary(summaryEl);
     this.renderSummaryComparison(sumSectionEl);
+    const remDiffEl = document.getElementById('compare-remarks-diff');
+    if (remDiffEl) this.renderRemarksDiff(remDiffEl);
     this.renderResults(resultsEl);
   },
 
@@ -178,6 +187,154 @@ const CompareView = {
     el.appendChild(section);
   },
 
+  renderRemarksDiff(el) {
+    clearEl(el);
+    const diff = this._remarksDiff;
+    if (!diff) return;
+
+    const s = diff.summary || {};
+    const newMissed = s.new_missed || 0;
+    const resolved = s.resolved_missed || 0;
+    const changed = s.functions_changed || 0;
+    const added = s.functions_added || 0;
+    const removed = s.functions_removed || 0;
+
+    if (changed === 0 && newMissed === 0 && resolved === 0) return;
+
+    const section = h('div', { class: 'compare-remarks-section' });
+    section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
+
+    const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'New Missed'),
+        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+      ));
+    if (resolved > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Resolved'),
+        h('div', { class: 'values', style: { color: 'var(--green)' } }, `-${formatNumber(resolved)}`)
+      ));
+    impactBar.appendChild(h('div', { class: 'summary-metric' },
+      h('div', { class: 'label' }, 'Functions Changed'),
+      h('div', { class: 'values' }, formatNumber(changed))
+    ));
+    if (added > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Added'),
+        h('div', { class: 'values' }, formatNumber(added))
+      ));
+    if (removed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Removed'),
+        h('div', { class: 'values' }, formatNumber(removed))
+      ));
+    section.appendChild(impactBar);
+
+    const functions = diff.functions || [];
+    if (!functions.length) { el.appendChild(section); return; }
+
+    const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
+    const thead = h('tr', {},
+      h('th', {}, 'Function'),
+      h('th', { style: { textAlign: 'right' } }, 'Before'),
+      h('th', { style: { textAlign: 'right' } }, 'After'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+    );
+    tbl.appendChild(h('thead', {}, thead));
+    const tbody = h('tbody', {});
+
+    functions.forEach((fn, idx) => {
+      const delta = fn.delta_missed;
+      const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const row = h('tr', { style: { cursor: 'pointer' },
+        onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
+      },
+        h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
+        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
+        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
+        h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+      );
+      tbody.appendChild(row);
+    });
+    tbl.appendChild(tbody);
+
+    const wrap = h('div', { class: 'top-units-wrap', style: { maxHeight: '300px', overflow: 'auto' } }, tbl);
+    section.appendChild(wrap);
+
+    const total = diff.total || 0;
+    const pageSize = 100;
+    this._remarkPageCount = Math.max(1, Math.ceil(total / pageSize));
+    if (total > functions.length) {
+      const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+      const prevBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage <= 0) return;
+        this._remarkPage--;
+        await this._fetchRemarkPage(el);
+      }}, '← Prev');
+      const nextBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage >= this._remarkPageCount - 1) return;
+        this._remarkPage++;
+        await this._fetchRemarkPage(el);
+      }}, 'Next →');
+      const pageLabel = h('span', { class: 'text-muted' }, `Page ${this._remarkPage + 1} of ${this._remarkPageCount} (${formatNumber(total)} changed)`);
+      pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+      section.appendChild(pager);
+    }
+
+    el.appendChild(section);
+  },
+
+  async _fetchRemarkPage(el) {
+    const res = await API.compareRemarks(this._baseId, this._candidateId, this._remarkPage * 100, 100);
+    if (res.ok && res.data) { this._remarksDiff = res.data; this.renderRemarksDiff(el); }
+  },
+
+  async _toggleFnDetail(fn, row, tbody, idx) {
+    const existingId = `fn-detail-${idx}`;
+    const existing = tbody.querySelector(`#${existingId}`);
+    if (existing) { existing.remove(); row.classList.remove('expanded'); return; }
+    row.classList.add('expanded');
+    const detailRow = h('tr', { id: existingId });
+    const cell = h('td', { colspan: '5', style: { padding: '8px 12px', background: 'var(--bg2)', fontSize: '11px' } });
+    cell.textContent = 'Loading…';
+    detailRow.appendChild(cell);
+    row.after(detailRow);
+
+    const res = await API.compareFunctionDetail(this._baseId, this._candidateId, fn.name);
+    clearEl(cell);
+    if (!res.ok) { cell.textContent = 'Failed to load detail.'; return; }
+    const d = res.data;
+    const added = d.added || [];
+    const removed = d.removed || [];
+
+    if (!added.length && !removed.length) { cell.textContent = 'No remark-level changes found.'; return; }
+
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+
+    const makeEntries = (items, sign, color) => items.map(r =>
+      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+        h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
+        h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
+        h('span', { style: { fontWeight: '500' } }, r.name || ''),
+        h('span', { class: 'text-muted' }, r.pass || ''),
+        h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
+      )
+    );
+
+    if (removed.length) {
+      cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
+      makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
+    }
+    if (added.length) {
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+    }
+  },
+
   renderResults(el) {
     if (!el || !this._results) return;
     clearEl(el);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index e540d2e4a4a99..bbe2361777ba8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -130,6 +130,8 @@ const API = {
     return API.get(url);
   },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
+  compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
+  compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 005b5c3e2ac94..7f389640ff29e 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -515,6 +515,8 @@ ul,ol{list-style:none}
 /* Compare Summary Section */
 .compare-summary-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
 .compare-summary-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);margin-bottom:14px}
+.compare-remarks-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
+.compare-remarks-section h3{font-size:13px;font-weight:600;margin-bottom:10px}
 .compare-health-delta{display:flex;align-items:center;gap:16px;padding:12px 0;margin-bottom:12px}
 .compare-health-value{font-family:var(--mono);font-size:28px;font-weight:700}
 .compare-health-arrow{font-size:18px}
@@ -868,6 +870,8 @@ const API = {
     return API.get(url);
   },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
+  compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
+  compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
   jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
@@ -3583,6 +3587,9 @@ const CompareView = {
   _results: null,
   _baseSummary: null,
   _candidateSummary: null,
+  _remarksDiff: null,
+  _remarkPage: 0,
+  _remarkPageCount: 1,
 
   async render(params) {
     this._baseId = params.base || null;
@@ -3597,6 +3604,7 @@ const CompareView = {
 
     container.appendChild(h('div', { id: 'compare-summary-section' }));
     container.appendChild(h('div', { class: 'summary-bar', id: 'compare-summary' }));
+    container.appendChild(h('div', { id: 'compare-remarks-diff' }));
     container.appendChild(h('div', { class: 'section-header' }, 'Unit Changes'));
     container.appendChild(h('div', { id: 'compare-results' }));
 
@@ -3631,14 +3639,17 @@ const CompareView = {
     const sumSectionEl = document.getElementById('compare-summary-section');
     if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(h('div', { class: 'text-muted mono', style: { padding: '16px' } }, 'Comparing…')); }
 
-    const [compareRes, baseSumRes, candSumRes] = await Promise.all([
+    const [compareRes, baseSumRes, candSumRes, remDiffRes] = await Promise.all([
       API.compare(this._baseId, this._candidateId),
       API.snapshotSummary(this._baseId).catch(() => ({ ok: false, data: {} })),
       API.snapshotSummary(this._candidateId).catch(() => ({ ok: false, data: {} })),
+      API.compareRemarks(this._baseId, this._candidateId, 0, 100).catch(() => ({ ok: false, data: null })),
     ]);
 
     this._baseSummary = baseSumRes.ok && baseSumRes.data ? baseSumRes.data : {};
     this._candidateSummary = candSumRes.ok && candSumRes.data ? candSumRes.data : {};
+    this._remarksDiff = remDiffRes.ok && remDiffRes.data ? remDiffRes.data : null;
+    this._remarkPage = 0;
 
     if (!compareRes.ok) {
       if (resultsEl) { clearEl(resultsEl); resultsEl.appendChild(UI.errorCard(compareRes.error || 'Compare failed', () => this.runCompare())); }
@@ -3648,6 +3659,8 @@ const CompareView = {
     this._results = compareRes.data;
     this.renderMatchSummary(summaryEl);
     this.renderSummaryComparison(sumSectionEl);
+    const remDiffEl = document.getElementById('compare-remarks-diff');
+    if (remDiffEl) this.renderRemarksDiff(remDiffEl);
     this.renderResults(resultsEl);
   },
 
@@ -3753,6 +3766,154 @@ const CompareView = {
     el.appendChild(section);
   },
 
+  renderRemarksDiff(el) {
+    clearEl(el);
+    const diff = this._remarksDiff;
+    if (!diff) return;
+
+    const s = diff.summary || {};
+    const newMissed = s.new_missed || 0;
+    const resolved = s.resolved_missed || 0;
+    const changed = s.functions_changed || 0;
+    const added = s.functions_added || 0;
+    const removed = s.functions_removed || 0;
+
+    if (changed === 0 && newMissed === 0 && resolved === 0) return;
+
+    const section = h('div', { class: 'compare-remarks-section' });
+    section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
+
+    const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'New Missed'),
+        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+      ));
+    if (resolved > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Resolved'),
+        h('div', { class: 'values', style: { color: 'var(--green)' } }, `-${formatNumber(resolved)}`)
+      ));
+    impactBar.appendChild(h('div', { class: 'summary-metric' },
+      h('div', { class: 'label' }, 'Functions Changed'),
+      h('div', { class: 'values' }, formatNumber(changed))
+    ));
+    if (added > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Added'),
+        h('div', { class: 'values' }, formatNumber(added))
+      ));
+    if (removed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
+        h('div', { class: 'label' }, 'Functions Removed'),
+        h('div', { class: 'values' }, formatNumber(removed))
+      ));
+    section.appendChild(impactBar);
+
+    const functions = diff.functions || [];
+    if (!functions.length) { el.appendChild(section); return; }
+
+    const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
+    const thead = h('tr', {},
+      h('th', {}, 'Function'),
+      h('th', { style: { textAlign: 'right' } }, 'Before'),
+      h('th', { style: { textAlign: 'right' } }, 'After'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
+      h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+    );
+    tbl.appendChild(h('thead', {}, thead));
+    const tbody = h('tbody', {});
+
+    functions.forEach((fn, idx) => {
+      const delta = fn.delta_missed;
+      const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const row = h('tr', { style: { cursor: 'pointer' },
+        onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
+      },
+        h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
+        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
+        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
+        h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+      );
+      tbody.appendChild(row);
+    });
+    tbl.appendChild(tbody);
+
+    const wrap = h('div', { class: 'top-units-wrap', style: { maxHeight: '300px', overflow: 'auto' } }, tbl);
+    section.appendChild(wrap);
+
+    const total = diff.total || 0;
+    const pageSize = 100;
+    this._remarkPageCount = Math.max(1, Math.ceil(total / pageSize));
+    if (total > functions.length) {
+      const pager = h('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginTop: '8px', fontSize: '12px' } });
+      const prevBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage <= 0) return;
+        this._remarkPage--;
+        await this._fetchRemarkPage(el);
+      }}, '← Prev');
+      const nextBtn = h('button', { class: 'triage-chip', onClick: async () => {
+        if (this._remarkPage >= this._remarkPageCount - 1) return;
+        this._remarkPage++;
+        await this._fetchRemarkPage(el);
+      }}, 'Next →');
+      const pageLabel = h('span', { class: 'text-muted' }, `Page ${this._remarkPage + 1} of ${this._remarkPageCount} (${formatNumber(total)} changed)`);
+      pager.appendChild(prevBtn); pager.appendChild(pageLabel); pager.appendChild(nextBtn);
+      section.appendChild(pager);
+    }
+
+    el.appendChild(section);
+  },
+
+  async _fetchRemarkPage(el) {
+    const res = await API.compareRemarks(this._baseId, this._candidateId, this._remarkPage * 100, 100);
+    if (res.ok && res.data) { this._remarksDiff = res.data; this.renderRemarksDiff(el); }
+  },
+
+  async _toggleFnDetail(fn, row, tbody, idx) {
+    const existingId = `fn-detail-${idx}`;
+    const existing = tbody.querySelector(`#${existingId}`);
+    if (existing) { existing.remove(); row.classList.remove('expanded'); return; }
+    row.classList.add('expanded');
+    const detailRow = h('tr', { id: existingId });
+    const cell = h('td', { colspan: '5', style: { padding: '8px 12px', background: 'var(--bg2)', fontSize: '11px' } });
+    cell.textContent = 'Loading…';
+    detailRow.appendChild(cell);
+    row.after(detailRow);
+
+    const res = await API.compareFunctionDetail(this._baseId, this._candidateId, fn.name);
+    clearEl(cell);
+    if (!res.ok) { cell.textContent = 'Failed to load detail.'; return; }
+    const d = res.data;
+    const added = d.added || [];
+    const removed = d.removed || [];
+
+    if (!added.length && !removed.length) { cell.textContent = 'No remark-level changes found.'; return; }
+
+    const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
+    const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
+
+    const makeEntries = (items, sign, color) => items.map(r =>
+      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+        h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
+        h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
+        h('span', { style: { fontWeight: '500' } }, r.name || ''),
+        h('span', { class: 'text-muted' }, r.pass || ''),
+        h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
+      )
+    );
+
+    if (removed.length) {
+      cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
+      makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
+    }
+    if (added.length) {
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+    }
+  },
+
   renderResults(el) {
     if (!el || !this._results) return;
     clearEl(el);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
index 57e78e075eda7..3e11b4d76be63 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/styles.css
@@ -503,6 +503,8 @@ ul,ol{list-style:none}
 /* Compare Summary Section */
 .compare-summary-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
 .compare-summary-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--fg3);margin-bottom:14px}
+.compare-remarks-section{background:var(--bg);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
+.compare-remarks-section h3{font-size:13px;font-weight:600;margin-bottom:10px}
 .compare-health-delta{display:flex;align-items:center;gap:16px;padding:12px 0;margin-bottom:12px}
 .compare-health-value{font-family:var(--mono);font-size:28px;font-weight:700}
 .compare-health-arrow{font-size:18px}

>From d035e94e42fd8351cf89b2d0cfb98de7f79b8de3 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 15 Jul 2026 05:00:02 +0530
Subject: [PATCH 28/41] [llvm-advisor] wire up Code Explorer links from remark
 diff drill-down + fix emitOptRemarks yaml

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Analysis/Clang/ClangAnalyzerUtils.cpp |  2 +-
 .../src/Client/HTTP/Assets/bundled.html       | 30 +++++++++++---
 .../src/Client/HTTP/Assets/compare.js         | 21 ++++++++--
 .../src/Client/HTTP/Assets/index_html.inc     | 30 +++++++++++---
 .../src/Client/HTTP/Assets/views.js           |  9 ++++-
 .../src/Client/HTTP/HTTPServer.cpp            | 40 +++++++++----------
 6 files changed, 92 insertions(+), 40 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp b/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
index 48d9a6f7514ab..b26a50c274d79 100644
--- a/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
+++ b/llvm/tools/llvm-advisor/src/Analysis/Clang/ClangAnalyzerUtils.cpp
@@ -402,7 +402,7 @@ llvm::advisor::emitOptRemarks(const CapabilityContext &Context,
     return createStringError(EC, "failed to create temp object file");
 
   SmallVector<std::string, 8> ExtraArgs = {
-      "-c", "-o", ObjPath.str().str(), "-fsave-optimization-record=bitstream",
+      "-c", "-o", ObjPath.str().str(), "-fsave-optimization-record=yaml",
       ("-foptimization-record-file=" + OutPath).str()};
   Expected<std::string> Result =
       runCompilerInvocation(Context, ExtraArgs, OutPath);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 9fce6a0b97bf8..d1a0c75ea95ca 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -3891,15 +3891,28 @@
     const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
     const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
 
-    const makeEntries = (items, sign, color) => items.map(r =>
-      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+    const makeEntries = (items, sign, color) => items.map(r => {
+      const hasLoc = r.file && r.line > 0;
+      const explorerLink = hasLoc
+        ? h('a', {
+            class: 'text-muted',
+            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
+            onClick: (e) => {
+              e.stopPropagation();
+              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            }
+          }, `${r.file.split('/').pop()}:${r.line}`)
+        : null;
+      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-      )
-    );
+        explorerLink,
+      );
+    });
 
     if (removed.length) {
       cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
@@ -5392,7 +5405,13 @@
   async render() {
     const container = h('div', {});
     container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
-    this._snap = State.get('currentSnapshot');
+    const params = State.get('routeParams') || {};
+    if (params.snapshot_id) {
+      const snaps = State.get('snapshots') || [];
+      this._snap = snaps.find(s => s.id === params.snapshot_id) || null;
+    } else {
+      this._snap = State.get('currentSnapshot');
+    }
     if (!this._snap) {
       container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
       Shell.renderMain(container);
@@ -5466,7 +5485,6 @@
     wrap.appendChild(sidebar); wrap.appendChild(mainCol);
     container.appendChild(wrap);
 
-    const params = State.get('routeParams') || {};
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index e66497a3fb055..b451f4d41386b 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -315,15 +315,28 @@ const CompareView = {
     const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
     const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
 
-    const makeEntries = (items, sign, color) => items.map(r =>
-      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+    const makeEntries = (items, sign, color) => items.map(r => {
+      const hasLoc = r.file && r.line > 0;
+      const explorerLink = hasLoc
+        ? h('a', {
+            class: 'text-muted',
+            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
+            onClick: (e) => {
+              e.stopPropagation();
+              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            }
+          }, `${r.file.split('/').pop()}:${r.line}`)
+        : null;
+      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-      )
-    );
+        explorerLink,
+      );
+    });
 
     if (removed.length) {
       cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 7f389640ff29e..408bf511f59de 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -3894,15 +3894,28 @@ const CompareView = {
     const TYPE_NAMES = { 1: 'passed', 2: 'missed', 3: 'analysis', 6: 'failure' };
     const TYPE_COLORS = { 1: 'var(--green)', 2: 'var(--orange)', 3: 'var(--teal)', 6: 'var(--red)' };
 
-    const makeEntries = (items, sign, color) => items.map(r =>
-      h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+    const makeEntries = (items, sign, color) => items.map(r => {
+      const hasLoc = r.file && r.line > 0;
+      const explorerLink = hasLoc
+        ? h('a', {
+            class: 'text-muted',
+            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
+            onClick: (e) => {
+              e.stopPropagation();
+              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            }
+          }, `${r.file.split('/').pop()}:${r.line}`)
+        : null;
+      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-      )
-    );
+        explorerLink,
+      );
+    });
 
     if (removed.length) {
       cell.appendChild(h('div', { style: { marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Removed (resolved):'));
@@ -5395,7 +5408,13 @@ const CodeExplorerView = {
   async render() {
     const container = h('div', {});
     container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
-    this._snap = State.get('currentSnapshot');
+    const params = State.get('routeParams') || {};
+    if (params.snapshot_id) {
+      const snaps = State.get('snapshots') || [];
+      this._snap = snaps.find(s => s.id === params.snapshot_id) || null;
+    } else {
+      this._snap = State.get('currentSnapshot');
+    }
     if (!this._snap) {
       container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
       Shell.renderMain(container);
@@ -5469,7 +5488,6 @@ const CodeExplorerView = {
     wrap.appendChild(sidebar); wrap.appendChild(mainCol);
     container.appendChild(wrap);
 
-    const params = State.get('routeParams') || {};
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index e650814fe0f3d..f29a341af36a8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1357,7 +1357,13 @@ const CodeExplorerView = {
   async render() {
     const container = h('div', {});
     container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Code Explorer'));
-    this._snap = State.get('currentSnapshot');
+    const params = State.get('routeParams') || {};
+    if (params.snapshot_id) {
+      const snaps = State.get('snapshots') || [];
+      this._snap = snaps.find(s => s.id === params.snapshot_id) || null;
+    } else {
+      this._snap = State.get('currentSnapshot');
+    }
     if (!this._snap) {
       container.appendChild(UI.emptyCard('No snapshot selected', 'Select a snapshot from the sidebar to explore source files.'));
       Shell.renderMain(container);
@@ -1431,7 +1437,6 @@ const CodeExplorerView = {
     wrap.appendChild(sidebar); wrap.appendChild(mainCol);
     container.appendChild(wrap);
 
-    const params = State.get('routeParams') || {};
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 30239d095c507..54ee818c50525 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1293,7 +1293,7 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
                                                  StringRef FuncName) {
   std::lock_guard<std::mutex> Lock(HeavyQueryMutex);
 
-  struct Remark { std::string Pass, Name; int64_t Type, Line, Hotness; };
+  struct Remark { std::string Pass, Name, File; int64_t Type, Line, Hotness; };
 
   auto collectRemarks = [&](StringRef SnapID) {
     std::vector<Remark> Out;
@@ -1319,10 +1319,12 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
         const json::Array *TypeCol = Cols->getArray("type");
         const json::Array *LineCol = Cols->getArray("line");
         const json::Array *HotnessCol = Cols->getArray("hotness");
+        const json::Array *FileCol = Cols->getArray("file");
         const json::Array *PassStrs = Strs->getArray("pass");
         const json::Array *NameStrs = Strs->getArray("name");
+        const json::Array *FileStrs = Strs->getArray("file");
         if (!FuncCol || !FuncStrs || !PassCol || !NameCol || !TypeCol ||
-            !LineCol || !HotnessCol || !PassStrs || !NameStrs) continue;
+            !LineCol || !HotnessCol || !FileCol || !PassStrs || !NameStrs || !FileStrs) continue;
         size_t N = FuncCol->size();
         for (size_t I = 0; I < N; ++I) {
           int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
@@ -1335,6 +1337,9 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
               ? (*PassStrs)[PI].getAsString().value_or("").str() : "";
           R.Name = NI >= 0 && NI < (int64_t)NameStrs->size()
               ? (*NameStrs)[NI].getAsString().value_or("").str() : "";
+          int64_t FILE_I = (*FileCol)[I].getAsInteger().value_or(-1);
+          R.File = FILE_I >= 0 && FILE_I < (int64_t)FileStrs->size()
+              ? (*FileStrs)[FILE_I].getAsString().value_or("").str() : "";
           R.Type = (*TypeCol)[I].getAsInteger().value_or(-1);
           R.Line = (*LineCol)[I].getAsInteger().value_or(-1);
           R.Hotness = (*HotnessCol)[I].getAsInteger().value_or(-1);
@@ -1353,32 +1358,23 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
   auto makeKey = [](const Remark &R) { return R.Pass + "\0" + R.Name + "\0" + std::to_string(R.Type); };
 
   StringMap<int64_t> BeforeCounts, AfterCounts;
+  StringMap<std::string> AfterFile; // first file seen for each key
+  StringMap<int64_t> AfterLine;      // first line seen for each key
   for (auto &R : BeforeRems) BeforeCounts[makeKey(R)]++;
-  for (auto &R : AfterRems) AfterCounts[makeKey(R)]++;
+  for (auto &R : AfterRems) {
+    std::string Key = makeKey(R);
+    AfterCounts[Key]++;
+    if (!AfterFile.count(Key)) {
+      AfterFile[Key] = R.File;
+      AfterLine[Key] = R.Line;
+    }
+  }
 
   json::Array Added, Removed;
   StringSet<> AllKeys;
   for (auto &KV : AfterCounts) AllKeys.insert(KV.first());
   for (auto &KV : BeforeCounts) AllKeys.insert(KV.first());
 
-  for (auto &K : AllKeys) {
-    int64_t B = BeforeCounts.lookup(K.getKey());
-    int64_t A = AfterCounts.lookup(K.getKey());
-    if (A > B) {
-      // Parse key back
-      StringRef S = K.getKey();
-      auto [PassName, Rest] = S.split('\0');
-      auto [Name, TypeStr] = Rest.split('\0');
-      int64_t Type = 0; TypeStr.getAsInteger(10, Type);
-      for (int64_t I = 0; I < A - B; ++I)
-        Added.push_back(json::Object{{"pass", PassName}, {"name", Name}, {"type", Type}, {"count", A - B}});
-      // Only push once
-      break;
-    }
-  }
-  // Rebuild properly
-  Added.clear();
-  Removed.clear();
   for (auto &K : AllKeys) {
     int64_t B = BeforeCounts.lookup(K.getKey());
     int64_t A = AfterCounts.lookup(K.getKey());
@@ -1391,6 +1387,8 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
     Entry["pass"] = Pass; Entry["name"] = Name; Entry["type"] = Type;
     Entry["before_count"] = B; Entry["after_count"] = A;
     Entry["delta"] = A - B;
+    Entry["file"] = AfterFile.lookup(K.getKey());
+    Entry["line"] = AfterLine.lookup(K.getKey());
     if (A > B) Added.push_back(std::move(Entry));
     else Removed.push_back(std::move(Entry));
   }

>From e7fc4c4b88a93f4cc3aa82d3a4ab696afbc89d7c Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Wed, 15 Jul 2026 07:02:50 +0530
Subject: [PATCH 29/41] [llvm-advisor] add severity computation to diff engine
 + net impact dashboard + red highlight for added remarks

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 30 +++++++++++++++----
 .../src/Client/HTTP/Assets/compare.js         | 30 +++++++++++++++----
 .../src/Client/HTTP/Assets/index_html.inc     | 30 +++++++++++++++----
 .../src/Client/HTTP/HTTPServer.cpp            | 11 +++++++
 4 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index d1a0c75ea95ca..101e6f6baf43a 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -3780,11 +3780,20 @@
     const section = h('div', { class: 'compare-remarks-section' });
     section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
 
+    const net = newMissed - resolved;
+    const netColor = net > 0 ? 'var(--orange)' : net < 0 ? 'var(--green)' : 'var(--fg)';
+    const netSign = net > 0 ? '+' : '';
+
     const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
-    if (newMissed > 0)
+    if (net !== 0)
       impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'Net'),
+        h('div', { class: 'values', style: { color: netColor } }, `${netSign}${formatNumber(net)}`)
+      ));
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
         h('div', { class: 'label' }, 'New Missed'),
-        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+        h('div', { class: 'values', style: { color: 'var(--red)' } }, `+${formatNumber(newMissed)}`)
       ));
     if (resolved > 0)
       impactBar.appendChild(h('div', { class: 'summary-metric' },
@@ -3810,6 +3819,7 @@
     const functions = diff.functions || [];
     if (!functions.length) { el.appendChild(section); return; }
 
+    const SEVERITY_COLORS = { minor: 'var(--fg3)', moderate: 'var(--orange)', critical: 'var(--red)' };
     const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
     const thead = h('tr', {},
       h('th', {}, 'Function'),
@@ -3817,6 +3827,7 @@
       h('th', { style: { textAlign: 'right' } }, 'After'),
       h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
       h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+      h('th', { style: { textAlign: 'center' } }, 'Severity'),
     );
     tbl.appendChild(h('thead', {}, thead));
     const tbody = h('tbody', {});
@@ -3824,14 +3835,21 @@
     functions.forEach((fn, idx) => {
       const delta = fn.delta_missed;
       const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const sev = fn.severity || 'minor';
+      const sevColor = SEVERITY_COLORS[sev] || 'var(--fg3)';
+      const beforeMissed = fn.before?.missed || 0;
+      const beforePassed = fn.before?.passed || 0;
+      const afterMissed = fn.after?.missed || 0;
+      const afterPassed = fn.after?.passed || 0;
       const row = h('tr', { style: { cursor: 'pointer' },
         onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
       },
         h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
-        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
-        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', title: `${beforeMissed} missed / ${beforePassed} passed` }, `${formatNumber(beforeMissed)}${beforePassed > 0 ? '/' + formatNumber(beforePassed) : ''}`),
+        h('td', { class: 'num', title: `${afterMissed} missed / ${afterPassed} passed` }, `${formatNumber(afterMissed)}${afterPassed > 0 ? '/' + formatNumber(afterPassed) : ''}`),
         h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
         h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+        h('td', { class: 'num', style: { color: sevColor, fontWeight: '600', fontSize: '10px', textTransform: 'uppercase', letterSpacing: '.5px' } }, sev),
       );
       tbody.appendChild(row);
     });
@@ -3919,8 +3937,8 @@
       makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
     }
     if (added.length) {
-      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
-      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--red)').forEach(e => cell.appendChild(e));
     }
   },
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index b451f4d41386b..4ae19812150de 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -204,11 +204,20 @@ const CompareView = {
     const section = h('div', { class: 'compare-remarks-section' });
     section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
 
+    const net = newMissed - resolved;
+    const netColor = net > 0 ? 'var(--orange)' : net < 0 ? 'var(--green)' : 'var(--fg)';
+    const netSign = net > 0 ? '+' : '';
+
     const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
-    if (newMissed > 0)
+    if (net !== 0)
       impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'Net'),
+        h('div', { class: 'values', style: { color: netColor } }, `${netSign}${formatNumber(net)}`)
+      ));
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
         h('div', { class: 'label' }, 'New Missed'),
-        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+        h('div', { class: 'values', style: { color: 'var(--red)' } }, `+${formatNumber(newMissed)}`)
       ));
     if (resolved > 0)
       impactBar.appendChild(h('div', { class: 'summary-metric' },
@@ -234,6 +243,7 @@ const CompareView = {
     const functions = diff.functions || [];
     if (!functions.length) { el.appendChild(section); return; }
 
+    const SEVERITY_COLORS = { minor: 'var(--fg3)', moderate: 'var(--orange)', critical: 'var(--red)' };
     const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
     const thead = h('tr', {},
       h('th', {}, 'Function'),
@@ -241,6 +251,7 @@ const CompareView = {
       h('th', { style: { textAlign: 'right' } }, 'After'),
       h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
       h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+      h('th', { style: { textAlign: 'center' } }, 'Severity'),
     );
     tbl.appendChild(h('thead', {}, thead));
     const tbody = h('tbody', {});
@@ -248,14 +259,21 @@ const CompareView = {
     functions.forEach((fn, idx) => {
       const delta = fn.delta_missed;
       const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const sev = fn.severity || 'minor';
+      const sevColor = SEVERITY_COLORS[sev] || 'var(--fg3)';
+      const beforeMissed = fn.before?.missed || 0;
+      const beforePassed = fn.before?.passed || 0;
+      const afterMissed = fn.after?.missed || 0;
+      const afterPassed = fn.after?.passed || 0;
       const row = h('tr', { style: { cursor: 'pointer' },
         onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
       },
         h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
-        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
-        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', title: `${beforeMissed} missed / ${beforePassed} passed` }, `${formatNumber(beforeMissed)}${beforePassed > 0 ? '/' + formatNumber(beforePassed) : ''}`),
+        h('td', { class: 'num', title: `${afterMissed} missed / ${afterPassed} passed` }, `${formatNumber(afterMissed)}${afterPassed > 0 ? '/' + formatNumber(afterPassed) : ''}`),
         h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
         h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+        h('td', { class: 'num', style: { color: sevColor, fontWeight: '600', fontSize: '10px', textTransform: 'uppercase', letterSpacing: '.5px' } }, sev),
       );
       tbody.appendChild(row);
     });
@@ -343,8 +361,8 @@ const CompareView = {
       makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
     }
     if (added.length) {
-      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
-      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--red)').forEach(e => cell.appendChild(e));
     }
   },
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 408bf511f59de..6d345cb0393dc 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -3783,11 +3783,20 @@ const CompareView = {
     const section = h('div', { class: 'compare-remarks-section' });
     section.appendChild(h('h3', { style: { margin: '0 0 10px' } }, 'Optimization Impact'));
 
+    const net = newMissed - resolved;
+    const netColor = net > 0 ? 'var(--orange)' : net < 0 ? 'var(--green)' : 'var(--fg)';
+    const netSign = net > 0 ? '+' : '';
+
     const impactBar = h('div', { style: { display: 'flex', gap: '10px', marginBottom: '12px', flexWrap: 'wrap' } });
-    if (newMissed > 0)
+    if (net !== 0)
       impactBar.appendChild(h('div', { class: 'summary-metric warn' },
+        h('div', { class: 'label' }, 'Net'),
+        h('div', { class: 'values', style: { color: netColor } }, `${netSign}${formatNumber(net)}`)
+      ));
+    if (newMissed > 0)
+      impactBar.appendChild(h('div', { class: 'summary-metric' },
         h('div', { class: 'label' }, 'New Missed'),
-        h('div', { class: 'values', style: { color: 'var(--orange)' } }, `+${formatNumber(newMissed)}`)
+        h('div', { class: 'values', style: { color: 'var(--red)' } }, `+${formatNumber(newMissed)}`)
       ));
     if (resolved > 0)
       impactBar.appendChild(h('div', { class: 'summary-metric' },
@@ -3813,6 +3822,7 @@ const CompareView = {
     const functions = diff.functions || [];
     if (!functions.length) { el.appendChild(section); return; }
 
+    const SEVERITY_COLORS = { minor: 'var(--fg3)', moderate: 'var(--orange)', critical: 'var(--red)' };
     const tbl = h('table', { class: 'top-units-table', style: { width: '100%' } });
     const thead = h('tr', {},
       h('th', {}, 'Function'),
@@ -3820,6 +3830,7 @@ const CompareView = {
       h('th', { style: { textAlign: 'right' } }, 'After'),
       h('th', { style: { textAlign: 'right' } }, '∆ Missed'),
       h('th', { style: { textAlign: 'right' } }, '∆ Total'),
+      h('th', { style: { textAlign: 'center' } }, 'Severity'),
     );
     tbl.appendChild(h('thead', {}, thead));
     const tbody = h('tbody', {});
@@ -3827,14 +3838,21 @@ const CompareView = {
     functions.forEach((fn, idx) => {
       const delta = fn.delta_missed;
       const color = delta > 0 ? 'var(--orange)' : delta < 0 ? 'var(--green)' : 'var(--fg)';
+      const sev = fn.severity || 'minor';
+      const sevColor = SEVERITY_COLORS[sev] || 'var(--fg3)';
+      const beforeMissed = fn.before?.missed || 0;
+      const beforePassed = fn.before?.passed || 0;
+      const afterMissed = fn.after?.missed || 0;
+      const afterPassed = fn.after?.passed || 0;
       const row = h('tr', { style: { cursor: 'pointer' },
         onClick: () => this._toggleFnDetail(fn, row, tbody, idx)
       },
         h('td', { class: 'mono', style: { fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, title: fn.name }, fn.name),
-        h('td', { class: 'num' }, formatNumber(fn.before?.missed || 0)),
-        h('td', { class: 'num' }, formatNumber(fn.after?.missed || 0)),
+        h('td', { class: 'num', title: `${beforeMissed} missed / ${beforePassed} passed` }, `${formatNumber(beforeMissed)}${beforePassed > 0 ? '/' + formatNumber(beforePassed) : ''}`),
+        h('td', { class: 'num', title: `${afterMissed} missed / ${afterPassed} passed` }, `${formatNumber(afterMissed)}${afterPassed > 0 ? '/' + formatNumber(afterPassed) : ''}`),
         h('td', { class: 'num', style: { color } }, `${delta >= 0 ? '+' : ''}${formatNumber(delta)}`),
         h('td', { class: 'num', style: { color: fn.delta_total > 0 ? 'var(--orange)' : fn.delta_total < 0 ? 'var(--green)' : '' } }, `${fn.delta_total >= 0 ? '+' : ''}${formatNumber(fn.delta_total)}`),
+        h('td', { class: 'num', style: { color: sevColor, fontWeight: '600', fontSize: '10px', textTransform: 'uppercase', letterSpacing: '.5px' } }, sev),
       );
       tbody.appendChild(row);
     });
@@ -3922,8 +3940,8 @@ const CompareView = {
       makeEntries(removed, '−', 'var(--green)').forEach(e => cell.appendChild(e));
     }
     if (added.length) {
-      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--orange)' } }, 'Added (new):'));
-      makeEntries(added, '+', 'var(--orange)').forEach(e => cell.appendChild(e));
+      cell.appendChild(h('div', { style: { marginTop: removed.length ? '8px' : 0, marginBottom: '4px', fontWeight: '600', color: 'var(--red)' } }, 'Added (new):'));
+      makeEntries(added, '+', 'var(--red)').forEach(e => cell.appendChild(e));
     }
   },
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 54ee818c50525..0d8ac658d33fa 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1191,6 +1191,14 @@ static HTTPResult handleGetCompareRemarks(CoreClient &Client,
     FuncProfile Before, After;
     int64_t DeltaMissed;
     int64_t DeltaTotal;
+    StringRef Severity;
+  };
+
+  auto getSeverity = [](int64_t DeltaMissed) -> StringRef {
+    int64_t AD = std::abs(DeltaMissed);
+    if (AD < 5) return "minor";
+    if (AD < 50) return "moderate";
+    return "critical";
   };
 
   SmallVector<FuncDiff, 256> Diffs;
@@ -1205,6 +1213,7 @@ static HTTPResult handleGetCompareRemarks(CoreClient &Client,
     D.After = KV.second;
     D.DeltaMissed = KV.second.Missed - B.Missed;
     D.DeltaTotal = KV.second.Total - B.Total;
+    D.Severity = getSeverity(D.DeltaMissed);
     if (D.DeltaMissed != 0 || D.DeltaTotal != 0 || B.Total == 0)
       Diffs.push_back(D);
   }
@@ -1215,6 +1224,7 @@ static HTTPResult handleGetCompareRemarks(CoreClient &Client,
     D.Before = KV.second;
     D.DeltaMissed = -KV.second.Missed;
     D.DeltaTotal = -KV.second.Total;
+    D.Severity = getSeverity(D.DeltaMissed);
     Diffs.push_back(D);
   }
 
@@ -1277,6 +1287,7 @@ static HTTPResult handleGetCompareRemarks(CoreClient &Client,
           JOS.attributeEnd();
           JOS.attribute("delta_missed", D.DeltaMissed);
           JOS.attribute("delta_total", D.DeltaTotal);
+          JOS.attribute("severity", D.Severity);
         });
       }
       JOS.arrayEnd();

>From 4c1bdf4bea21fe7054c287deb0b71070b812760e Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 19 Jul 2026 02:41:27 +0530
Subject: [PATCH 30/41] [llvm-advisor] make entire remark row clickable to open
 Code Explorer at source location

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 27 ++++++++++---------
 .../src/Client/HTTP/Assets/compare.js         | 27 ++++++++++---------
 .../src/Client/HTTP/Assets/index_html.inc     | 27 ++++++++++---------
 3 files changed, 45 insertions(+), 36 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 101e6f6baf43a..1466e384daad4 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -3911,24 +3911,27 @@
 
     const makeEntries = (items, sign, color) => items.map(r => {
       const hasLoc = r.file && r.line > 0;
-      const explorerLink = hasLoc
-        ? h('a', {
-            class: 'text-muted',
-            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
-            onClick: (e) => {
-              e.stopPropagation();
-              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
-            }
-          }, `${r.file.split('/').pop()}:${r.line}`)
+      const locLabel = hasLoc ? `${r.file.split('/').pop()}:${r.line}` : '';
+      const goToExplorer = hasLoc
+        ? (e) => {
+            e.stopPropagation();
+            State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+          }
         : null;
-      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+      return h('div', {
+        style: { display: 'flex', gap: '8px', padding: '4px 6px', alignItems: 'baseline', cursor: hasLoc ? 'pointer' : 'default', borderRadius: '4px' },
+        onClick: goToExplorer,
+        onMouseEnter: (e) => { if (hasLoc) e.currentTarget.style.background = 'var(--bg)'; },
+        onMouseLeave: (e) => { if (hasLoc) e.currentTarget.style.background = ''; },
+        title: hasLoc ? `Click to open ${locLabel} in Code Explorer` : ''
+      },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-        explorerLink,
+        hasLoc ? h('span', { class: 'text-muted', style: { fontSize: '10px', textDecoration: 'underline' } }, locLabel) : null,
       );
     });
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index 4ae19812150de..cea8bdcd283de 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -335,24 +335,27 @@ const CompareView = {
 
     const makeEntries = (items, sign, color) => items.map(r => {
       const hasLoc = r.file && r.line > 0;
-      const explorerLink = hasLoc
-        ? h('a', {
-            class: 'text-muted',
-            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
-            onClick: (e) => {
-              e.stopPropagation();
-              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
-            }
-          }, `${r.file.split('/').pop()}:${r.line}`)
+      const locLabel = hasLoc ? `${r.file.split('/').pop()}:${r.line}` : '';
+      const goToExplorer = hasLoc
+        ? (e) => {
+            e.stopPropagation();
+            State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+          }
         : null;
-      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+      return h('div', {
+        style: { display: 'flex', gap: '8px', padding: '4px 6px', alignItems: 'baseline', cursor: hasLoc ? 'pointer' : 'default', borderRadius: '4px' },
+        onClick: goToExplorer,
+        onMouseEnter: (e) => { if (hasLoc) e.currentTarget.style.background = 'var(--bg)'; },
+        onMouseLeave: (e) => { if (hasLoc) e.currentTarget.style.background = ''; },
+        title: hasLoc ? `Click to open ${locLabel} in Code Explorer` : ''
+      },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-        explorerLink,
+        hasLoc ? h('span', { class: 'text-muted', style: { fontSize: '10px', textDecoration: 'underline' } }, locLabel) : null,
       );
     });
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 6d345cb0393dc..0649e945fb362 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -3914,24 +3914,27 @@ const CompareView = {
 
     const makeEntries = (items, sign, color) => items.map(r => {
       const hasLoc = r.file && r.line > 0;
-      const explorerLink = hasLoc
-        ? h('a', {
-            class: 'text-muted',
-            style: { fontSize: '10px', cursor: 'pointer', textDecoration: 'underline' },
-            onClick: (e) => {
-              e.stopPropagation();
-              State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-              Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
-            }
-          }, `${r.file.split('/').pop()}:${r.line}`)
+      const locLabel = hasLoc ? `${r.file.split('/').pop()}:${r.line}` : '';
+      const goToExplorer = hasLoc
+        ? (e) => {
+            e.stopPropagation();
+            State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
+            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+          }
         : null;
-      return h('div', { style: { display: 'flex', gap: '8px', padding: '2px 0', alignItems: 'baseline' } },
+      return h('div', {
+        style: { display: 'flex', gap: '8px', padding: '4px 6px', alignItems: 'baseline', cursor: hasLoc ? 'pointer' : 'default', borderRadius: '4px' },
+        onClick: goToExplorer,
+        onMouseEnter: (e) => { if (hasLoc) e.currentTarget.style.background = 'var(--bg)'; },
+        onMouseLeave: (e) => { if (hasLoc) e.currentTarget.style.background = ''; },
+        title: hasLoc ? `Click to open ${locLabel} in Code Explorer` : ''
+      },
         h('span', { style: { color, fontWeight: '600', minWidth: '16px' } }, sign),
         h('span', { style: { color: TYPE_COLORS[r.type] || 'var(--fg3)', minWidth: '60px' } }, TYPE_NAMES[r.type] || '?'),
         h('span', { style: { fontWeight: '500' } }, r.name || ''),
         h('span', { class: 'text-muted' }, r.pass || ''),
         h('span', { style: { color: color, fontSize: '10px' } }, `×${Math.abs(r.delta || r.after_count - r.before_count)}`),
-        explorerLink,
+        hasLoc ? h('span', { class: 'text-muted', style: { fontSize: '10px', textDecoration: 'underline' } }, locLabel) : null,
       );
     });
 

>From 3365f90d93b365b93f2cfffafbf71ee2e0c6cb94 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 19 Jul 2026 03:19:56 +0530
Subject: [PATCH 31/41] [llvm-advisor] fix diff key separator and pass specific
 remark filters to Code Explorer

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html         | 17 ++++++++++++++++-
 .../src/Client/HTTP/Assets/compare.js           |  7 ++++++-
 .../src/Client/HTTP/Assets/index_html.inc       | 17 ++++++++++++++++-
 .../src/Client/HTTP/Assets/views.js             | 10 ++++++++++
 .../llvm-advisor/src/Client/HTTP/HTTPServer.cpp |  4 +++-
 5 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 1466e384daad4..315042808feab 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -3916,7 +3916,12 @@
         ? (e) => {
             e.stopPropagation();
             State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            const qs = new URLSearchParams();
+            qs.set('path', r.file);
+            qs.set('line', String(r.line));
+            if (r.pass) qs.set('pass', r.pass);
+            if (r.name) qs.set('name', r.name);
+            Router.navigate(`/explorer?${qs.toString()}`);
           }
         : null;
       return h('div', {
@@ -5509,6 +5514,16 @@
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
+    // Apply remark filters from URL params (e.g., from diff drill-down)
+    if (params.pass) {
+      passInput.value = params.pass;
+      this._filters.pass = params.pass;
+    }
+    if (params.name) {
+      nameInput.value = params.name;
+      this._filters.name = params.name;
+    }
+
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
       if (match) match.style.background = 'var(--bg2)';
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index cea8bdcd283de..aecb3f9caa6ae 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -340,7 +340,12 @@ const CompareView = {
         ? (e) => {
             e.stopPropagation();
             State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            const qs = new URLSearchParams();
+            qs.set('path', r.file);
+            qs.set('line', String(r.line));
+            if (r.pass) qs.set('pass', r.pass);
+            if (r.name) qs.set('name', r.name);
+            Router.navigate(`/explorer?${qs.toString()}`);
           }
         : null;
       return h('div', {
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 0649e945fb362..ea02859c43ea0 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -3919,7 +3919,12 @@ const CompareView = {
         ? (e) => {
             e.stopPropagation();
             State.set('currentSnapshot', State.get('snapshots').find(s => s.id === this._candidateId) || null);
-            Router.navigate(`/explorer?path=${encodeURIComponent(r.file)}&line=${r.line}`);
+            const qs = new URLSearchParams();
+            qs.set('path', r.file);
+            qs.set('line', String(r.line));
+            if (r.pass) qs.set('pass', r.pass);
+            if (r.name) qs.set('name', r.name);
+            Router.navigate(`/explorer?${qs.toString()}`);
           }
         : null;
       return h('div', {
@@ -5512,6 +5517,16 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
+    // Apply remark filters from URL params (e.g., from diff drill-down)
+    if (params.pass) {
+      passInput.value = params.pass;
+      this._filters.pass = params.pass;
+    }
+    if (params.name) {
+      nameInput.value = params.name;
+      this._filters.name = params.name;
+    }
+
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
       if (match) match.style.background = 'var(--bg2)';
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index f29a341af36a8..0705fe88bdecc 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1440,6 +1440,16 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
+    // Apply remark filters from URL params (e.g., from diff drill-down)
+    if (params.pass) {
+      passInput.value = params.pass;
+      this._filters.pass = params.pass;
+    }
+    if (params.name) {
+      nameInput.value = params.name;
+      this._filters.name = params.name;
+    }
+
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
       if (match) match.style.background = 'var(--bg2)';
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 0d8ac658d33fa..a2de3b0d89de2 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1366,7 +1366,9 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
 
   // Match by (pass, name, type) — group and count
   struct Key { std::string Pass, Name; int64_t Type; };
-  auto makeKey = [](const Remark &R) { return R.Pass + "\0" + R.Name + "\0" + std::to_string(R.Type); };
+  auto makeKey = [](const Remark &R) {
+    return R.Pass + std::string(1, '\0') + R.Name + std::string(1, '\0') + std::to_string(R.Type);
+  };
 
   StringMap<int64_t> BeforeCounts, AfterCounts;
   StringMap<std::string> AfterFile; // first file seen for each key

>From 60d7d13217419d7a68f5a0e5dda98f93e93e4104 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Mon, 20 Jul 2026 22:30:44 +0530
Subject: [PATCH 32/41] [llvm-advisor] remove unnecessary comments from diff
 engine and explorer filter wiring

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html  | 1 -
 .../tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc | 1 -
 llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js      | 1 -
 llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp       | 5 ++---
 4 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 315042808feab..6a5e6c90d8739 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -5514,7 +5514,6 @@
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    // Apply remark filters from URL params (e.g., from diff drill-down)
     if (params.pass) {
       passInput.value = params.pass;
       this._filters.pass = params.pass;
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index ea02859c43ea0..93cf50dc4e020 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -5517,7 +5517,6 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    // Apply remark filters from URL params (e.g., from diff drill-down)
     if (params.pass) {
       passInput.value = params.pass;
       this._filters.pass = params.pass;
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 0705fe88bdecc..e0a6471be7abb 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1440,7 +1440,6 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    // Apply remark filters from URL params (e.g., from diff drill-down)
     if (params.pass) {
       passInput.value = params.pass;
       this._filters.pass = params.pass;
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index a2de3b0d89de2..37455546c01db 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1364,15 +1364,14 @@ static HTTPResult handleGetCompareFunctionDetail(CoreClient &Client,
   std::vector<Remark> BeforeRems = collectRemarks(Before);
   std::vector<Remark> AfterRems = collectRemarks(After);
 
-  // Match by (pass, name, type) — group and count
   struct Key { std::string Pass, Name; int64_t Type; };
   auto makeKey = [](const Remark &R) {
     return R.Pass + std::string(1, '\0') + R.Name + std::string(1, '\0') + std::to_string(R.Type);
   };
 
   StringMap<int64_t> BeforeCounts, AfterCounts;
-  StringMap<std::string> AfterFile; // first file seen for each key
-  StringMap<int64_t> AfterLine;      // first line seen for each key
+  StringMap<std::string> AfterFile;
+  StringMap<int64_t> AfterLine;
   for (auto &R : BeforeRems) BeforeCounts[makeKey(R)]++;
   for (auto &R : AfterRems) {
     std::string Key = makeKey(R);

>From 8aa89ecb0b9021aebada294794e7b4092bb556c1 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 2 Aug 2026 05:45:30 +0530
Subject: [PATCH 33/41] [llvm-advisor] redesign heatmap with visual hotness
 bars, status chips, and project stats sidebar

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 101 +++++++++++++-----
 .../src/Client/HTTP/Assets/index_html.inc     | 101 +++++++++++++-----
 .../src/Client/HTTP/Assets/views.js           | 101 +++++++++++++-----
 3 files changed, 216 insertions(+), 87 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 6a5e6c90d8739..22530061fca81 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -5345,7 +5345,6 @@
 const HeatmapView = {
   async render() {
     const container = h('div', {});
-    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
 
     const snap = State.get('currentSnapshot');
     if (!snap) {
@@ -5386,36 +5385,80 @@
       return;
     }
 
-    // Sort by count descending
-    allHotspots.sort((a, b) => b.count - a.count);
-
-    // Render table
-    const table = h('table', { class: 'data-table' });
-    const thead = h('thead', {},
-      h('tr', {},
-        h('th', {}, 'Function'),
-        h('th', {}, 'File'),
-        h('th', {}, 'Line'),
-        h('th', {}, 'Count'),
-        h('th', {}, 'Max Hotness')
-      )
-    );
-    table.appendChild(thead);
-
-    const tbody = h('tbody');
-    allHotspots.forEach(hotspot => {
-      const row = h('tr', {},
-        h('td', { class: 'mono' }, hotspot.function || ''),
-        h('td', { class: 'mono' }, hotspot.file || ''),
-        h('td', { class: 'mono' }, String(hotspot.line || '')),
-        h('td', {}, String(hotspot.count || 0)),
-        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
-      );
-      tbody.appendChild(row);
+    allHotspots.sort((a, b) => (b.max_hotness || 0) - (a.max_hotness || 0));
+
+    const maxHotness = Math.max(...allHotspots.map(h => h.max_hotness || 0), 1);
+    const total = allHotspots.length;
+    const withHotness = allHotspots.filter(h => (h.max_hotness || 0) > 0).length;
+
+    const getStatus = (hotness) => {
+      if (!hotness || maxHotness <= 1) return { label: 'Low', color: '#5DB8A8' };
+      const pct = hotness / maxHotness;
+      if (pct >= 0.8) return { label: 'Critical', color: '#E06C75' };
+      if (pct >= 0.5) return { label: 'High', color: '#D4A574' };
+      if (pct >= 0.2) return { label: 'Medium', color: '#E5C07B' };
+      return { label: 'Low', color: '#5DB8A8' };
+    };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
+
+    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
+    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
+    const statItems = [
+      { label: 'Total Hotspots', value: total },
+      { label: 'With Hotness', value: withHotness },
+      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
+    ];
+    statItems.forEach(s => {
+      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
+        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+      ));
     });
-    table.appendChild(tbody);
+    wrap.appendChild(stats);
+
+    const main = h('div', { style: { flex: 1, minWidth: 0 } });
+    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
+    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
 
-    container.appendChild(table);
+    allHotspots.forEach(hs => {
+      const st = getStatus(hs.max_hotness);
+      const pct = maxHotness > 1 ? ((hs.max_hotness || 0) / maxHotness * 100).toFixed(1) : '0.0';
+      const file = (hs.file || '').split('/').pop() || 'unknown';
+      const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
+
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+
+      row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
+      ));
+
+      row.appendChild(h('div', { style: { width: '200px', minWidth: '160px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontFamily: 'var(--mono)', fontWeight: '500' } }, hs.function || 'unknown'));
+
+      row.appendChild(h('div', { style: { width: '160px', minWidth: '120px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--fg3)' } }, loc));
+
+      const barWrap = h('div', { style: { flex: 1, display: 'flex', alignItems: 'center', gap: '8px' } });
+      const barTrack = h('div', { style: { flex: 1, height: '6px', background: 'var(--bg3)', borderRadius: '3px', overflow: 'hidden' } });
+      const barFill = h('div', { style: { width: `${pct}%`, height: '100%', background: st.color, borderRadius: '3px', transition: 'width 0.3s' } });
+      barTrack.appendChild(barFill);
+      barWrap.appendChild(barTrack);
+      barWrap.appendChild(h('span', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, `${pct}%`));
+      row.appendChild(barWrap);
+
+      row.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: '10px', fontSize: '10px', fontWeight: '600', background: st.color + '22', color: st.color } }, st.label)
+      ));
+
+      row.appendChild(h('div', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, String(hs.count || 0)));
+
+      rows.appendChild(row);
+    });
+
+    main.appendChild(rows);
+    wrap.appendChild(main);
+    container.appendChild(wrap);
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 93cf50dc4e020..58f07d5f7ad20 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -5348,7 +5348,6 @@ const SettingsView = {
 const HeatmapView = {
   async render() {
     const container = h('div', {});
-    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
 
     const snap = State.get('currentSnapshot');
     if (!snap) {
@@ -5389,36 +5388,80 @@ const HeatmapView = {
       return;
     }
 
-    // Sort by count descending
-    allHotspots.sort((a, b) => b.count - a.count);
-
-    // Render table
-    const table = h('table', { class: 'data-table' });
-    const thead = h('thead', {},
-      h('tr', {},
-        h('th', {}, 'Function'),
-        h('th', {}, 'File'),
-        h('th', {}, 'Line'),
-        h('th', {}, 'Count'),
-        h('th', {}, 'Max Hotness')
-      )
-    );
-    table.appendChild(thead);
-
-    const tbody = h('tbody');
-    allHotspots.forEach(hotspot => {
-      const row = h('tr', {},
-        h('td', { class: 'mono' }, hotspot.function || ''),
-        h('td', { class: 'mono' }, hotspot.file || ''),
-        h('td', { class: 'mono' }, String(hotspot.line || '')),
-        h('td', {}, String(hotspot.count || 0)),
-        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
-      );
-      tbody.appendChild(row);
+    allHotspots.sort((a, b) => (b.max_hotness || 0) - (a.max_hotness || 0));
+
+    const maxHotness = Math.max(...allHotspots.map(h => h.max_hotness || 0), 1);
+    const total = allHotspots.length;
+    const withHotness = allHotspots.filter(h => (h.max_hotness || 0) > 0).length;
+
+    const getStatus = (hotness) => {
+      if (!hotness || maxHotness <= 1) return { label: 'Low', color: '#5DB8A8' };
+      const pct = hotness / maxHotness;
+      if (pct >= 0.8) return { label: 'Critical', color: '#E06C75' };
+      if (pct >= 0.5) return { label: 'High', color: '#D4A574' };
+      if (pct >= 0.2) return { label: 'Medium', color: '#E5C07B' };
+      return { label: 'Low', color: '#5DB8A8' };
+    };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
+
+    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
+    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
+    const statItems = [
+      { label: 'Total Hotspots', value: total },
+      { label: 'With Hotness', value: withHotness },
+      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
+    ];
+    statItems.forEach(s => {
+      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
+        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+      ));
     });
-    table.appendChild(tbody);
+    wrap.appendChild(stats);
+
+    const main = h('div', { style: { flex: 1, minWidth: 0 } });
+    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
+    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
 
-    container.appendChild(table);
+    allHotspots.forEach(hs => {
+      const st = getStatus(hs.max_hotness);
+      const pct = maxHotness > 1 ? ((hs.max_hotness || 0) / maxHotness * 100).toFixed(1) : '0.0';
+      const file = (hs.file || '').split('/').pop() || 'unknown';
+      const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
+
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+
+      row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
+      ));
+
+      row.appendChild(h('div', { style: { width: '200px', minWidth: '160px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontFamily: 'var(--mono)', fontWeight: '500' } }, hs.function || 'unknown'));
+
+      row.appendChild(h('div', { style: { width: '160px', minWidth: '120px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--fg3)' } }, loc));
+
+      const barWrap = h('div', { style: { flex: 1, display: 'flex', alignItems: 'center', gap: '8px' } });
+      const barTrack = h('div', { style: { flex: 1, height: '6px', background: 'var(--bg3)', borderRadius: '3px', overflow: 'hidden' } });
+      const barFill = h('div', { style: { width: `${pct}%`, height: '100%', background: st.color, borderRadius: '3px', transition: 'width 0.3s' } });
+      barTrack.appendChild(barFill);
+      barWrap.appendChild(barTrack);
+      barWrap.appendChild(h('span', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, `${pct}%`));
+      row.appendChild(barWrap);
+
+      row.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: '10px', fontSize: '10px', fontWeight: '600', background: st.color + '22', color: st.color } }, st.label)
+      ));
+
+      row.appendChild(h('div', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, String(hs.count || 0)));
+
+      rows.appendChild(row);
+    });
+
+    main.appendChild(rows);
+    wrap.appendChild(main);
+    container.appendChild(wrap);
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index e0a6471be7abb..96cff8fc87a80 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1271,7 +1271,6 @@ const SettingsView = {
 const HeatmapView = {
   async render() {
     const container = h('div', {});
-    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots'));
 
     const snap = State.get('currentSnapshot');
     if (!snap) {
@@ -1312,36 +1311,80 @@ const HeatmapView = {
       return;
     }
 
-    // Sort by count descending
-    allHotspots.sort((a, b) => b.count - a.count);
-
-    // Render table
-    const table = h('table', { class: 'data-table' });
-    const thead = h('thead', {},
-      h('tr', {},
-        h('th', {}, 'Function'),
-        h('th', {}, 'File'),
-        h('th', {}, 'Line'),
-        h('th', {}, 'Count'),
-        h('th', {}, 'Max Hotness')
-      )
-    );
-    table.appendChild(thead);
-
-    const tbody = h('tbody');
-    allHotspots.forEach(hotspot => {
-      const row = h('tr', {},
-        h('td', { class: 'mono' }, hotspot.function || ''),
-        h('td', { class: 'mono' }, hotspot.file || ''),
-        h('td', { class: 'mono' }, String(hotspot.line || '')),
-        h('td', {}, String(hotspot.count || 0)),
-        h('td', {}, String(hotspot.max_hotness !== undefined ? hotspot.max_hotness : '-'))
-      );
-      tbody.appendChild(row);
+    allHotspots.sort((a, b) => (b.max_hotness || 0) - (a.max_hotness || 0));
+
+    const maxHotness = Math.max(...allHotspots.map(h => h.max_hotness || 0), 1);
+    const total = allHotspots.length;
+    const withHotness = allHotspots.filter(h => (h.max_hotness || 0) > 0).length;
+
+    const getStatus = (hotness) => {
+      if (!hotness || maxHotness <= 1) return { label: 'Low', color: '#5DB8A8' };
+      const pct = hotness / maxHotness;
+      if (pct >= 0.8) return { label: 'Critical', color: '#E06C75' };
+      if (pct >= 0.5) return { label: 'High', color: '#D4A574' };
+      if (pct >= 0.2) return { label: 'Medium', color: '#E5C07B' };
+      return { label: 'Low', color: '#5DB8A8' };
+    };
+
+    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
+
+    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
+    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
+    const statItems = [
+      { label: 'Total Hotspots', value: total },
+      { label: 'With Hotness', value: withHotness },
+      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
+    ];
+    statItems.forEach(s => {
+      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
+        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+      ));
     });
-    table.appendChild(tbody);
+    wrap.appendChild(stats);
+
+    const main = h('div', { style: { flex: 1, minWidth: 0 } });
+    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
+    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
+
+    allHotspots.forEach(hs => {
+      const st = getStatus(hs.max_hotness);
+      const pct = maxHotness > 1 ? ((hs.max_hotness || 0) / maxHotness * 100).toFixed(1) : '0.0';
+      const file = (hs.file || '').split('/').pop() || 'unknown';
+      const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-    container.appendChild(table);
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+
+      row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
+      ));
+
+      row.appendChild(h('div', { style: { width: '200px', minWidth: '160px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontFamily: 'var(--mono)', fontWeight: '500' } }, hs.function || 'unknown'));
+
+      row.appendChild(h('div', { style: { width: '160px', minWidth: '120px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--fg3)' } }, loc));
+
+      const barWrap = h('div', { style: { flex: 1, display: 'flex', alignItems: 'center', gap: '8px' } });
+      const barTrack = h('div', { style: { flex: 1, height: '6px', background: 'var(--bg3)', borderRadius: '3px', overflow: 'hidden' } });
+      const barFill = h('div', { style: { width: `${pct}%`, height: '100%', background: st.color, borderRadius: '3px', transition: 'width 0.3s' } });
+      barTrack.appendChild(barFill);
+      barWrap.appendChild(barTrack);
+      barWrap.appendChild(h('span', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, `${pct}%`));
+      row.appendChild(barWrap);
+
+      row.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } },
+        h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: '10px', fontSize: '10px', fontWeight: '600', background: st.color + '22', color: st.color } }, st.label)
+      ));
+
+      row.appendChild(h('div', { style: { width: '50px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', color: 'var(--fg3)' } }, String(hs.count || 0)));
+
+      rows.appendChild(row);
+    });
+
+    main.appendChild(rows);
+    wrap.appendChild(main);
+    container.appendChild(wrap);
   },
 };
 

>From 4763fd99f734abbf6435414712d013f7971d150a Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 2 Aug 2026 05:52:21 +0530
Subject: [PATCH 34/41] [llvm-advisor] make heatmap stats horizontal and add
 labeled table headers

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 54 +++++++++++--------
 .../src/Client/HTTP/Assets/index_html.inc     | 54 +++++++++++--------
 .../src/Client/HTTP/Assets/views.js           | 54 +++++++++++--------
 3 files changed, 96 insertions(+), 66 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 22530061fca81..11f86727e8504 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -5400,28 +5400,39 @@
       return { label: 'Low', color: '#5DB8A8' };
     };
 
-    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
-
-    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
-    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
-    const statItems = [
-      { label: 'Total Hotspots', value: total },
-      { label: 'With Hotness', value: withHotness },
-      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
-    ];
-    statItems.forEach(s => {
-      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
-        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
-        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+    const statusCounts = { Critical: 0, High: 0, Medium: 0, Low: 0 };
+    allHotspots.forEach(h => { statusCounts[getStatus(h.max_hotness).label]++; });
+
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots Analysis'));
+
+    const statsRow = h('div', { style: { display: 'flex', gap: '12px', marginBottom: '20px' } });
+    [
+      { label: 'Total Hotspots', value: total, color: 'var(--fg)' },
+      { label: 'With Hotness', value: withHotness, color: 'var(--fg)' },
+      { label: 'Critical', value: statusCounts.Critical, color: '#E06C75' },
+      { label: 'High', value: statusCounts.High, color: '#D4A574' },
+      { label: 'Medium', value: statusCounts.Medium, color: '#E5C07B' },
+      { label: 'Low', value: statusCounts.Low, color: '#5DB8A8' },
+    ].forEach(s => {
+      statsRow.appendChild(h('div', { style: { flex: 1, padding: '10px 14px', background: 'var(--bg2)', borderRadius: '8px', textAlign: 'center' } },
+        h('div', { style: { fontSize: '20px', fontWeight: '700', color: s.color } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '4px', fontWeight: '500' } }, s.label)
       ));
     });
-    wrap.appendChild(stats);
+    container.appendChild(statsRow);
+
+    const tableWrap = h('div', { style: { background: 'var(--bg2)', borderRadius: '8px', overflow: 'hidden' } });
 
-    const main = h('div', { style: { flex: 1, minWidth: 0 } });
-    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
-    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+    const header = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', background: 'var(--bg3)', fontSize: '11px', fontWeight: '600', color: 'var(--fg3)', textTransform: 'uppercase', letterSpacing: '0.5px' } });
+    header.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } }, ''));
+    header.appendChild(h('div', { style: { width: '200px', minWidth: '160px' } }, 'Function'));
+    header.appendChild(h('div', { style: { width: '160px', minWidth: '120px' } }, 'Location'));
+    header.appendChild(h('div', { style: { flex: 1 } }, 'Hotness'));
+    header.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } }, 'Status'));
+    header.appendChild(h('div', { style: { width: '50px', textAlign: 'right' } }, 'Count'));
+    tableWrap.appendChild(header);
 
-    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column' } });
 
     allHotspots.forEach(hs => {
       const st = getStatus(hs.max_hotness);
@@ -5429,7 +5440,7 @@
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -5456,9 +5467,8 @@
       rows.appendChild(row);
     });
 
-    main.appendChild(rows);
-    wrap.appendChild(main);
-    container.appendChild(wrap);
+    tableWrap.appendChild(rows);
+    container.appendChild(tableWrap);
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 58f07d5f7ad20..8a3aca87982cf 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -5403,28 +5403,39 @@ const HeatmapView = {
       return { label: 'Low', color: '#5DB8A8' };
     };
 
-    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
-
-    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
-    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
-    const statItems = [
-      { label: 'Total Hotspots', value: total },
-      { label: 'With Hotness', value: withHotness },
-      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
-    ];
-    statItems.forEach(s => {
-      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
-        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
-        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+    const statusCounts = { Critical: 0, High: 0, Medium: 0, Low: 0 };
+    allHotspots.forEach(h => { statusCounts[getStatus(h.max_hotness).label]++; });
+
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots Analysis'));
+
+    const statsRow = h('div', { style: { display: 'flex', gap: '12px', marginBottom: '20px' } });
+    [
+      { label: 'Total Hotspots', value: total, color: 'var(--fg)' },
+      { label: 'With Hotness', value: withHotness, color: 'var(--fg)' },
+      { label: 'Critical', value: statusCounts.Critical, color: '#E06C75' },
+      { label: 'High', value: statusCounts.High, color: '#D4A574' },
+      { label: 'Medium', value: statusCounts.Medium, color: '#E5C07B' },
+      { label: 'Low', value: statusCounts.Low, color: '#5DB8A8' },
+    ].forEach(s => {
+      statsRow.appendChild(h('div', { style: { flex: 1, padding: '10px 14px', background: 'var(--bg2)', borderRadius: '8px', textAlign: 'center' } },
+        h('div', { style: { fontSize: '20px', fontWeight: '700', color: s.color } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '4px', fontWeight: '500' } }, s.label)
       ));
     });
-    wrap.appendChild(stats);
+    container.appendChild(statsRow);
+
+    const tableWrap = h('div', { style: { background: 'var(--bg2)', borderRadius: '8px', overflow: 'hidden' } });
 
-    const main = h('div', { style: { flex: 1, minWidth: 0 } });
-    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
-    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+    const header = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', background: 'var(--bg3)', fontSize: '11px', fontWeight: '600', color: 'var(--fg3)', textTransform: 'uppercase', letterSpacing: '0.5px' } });
+    header.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } }, ''));
+    header.appendChild(h('div', { style: { width: '200px', minWidth: '160px' } }, 'Function'));
+    header.appendChild(h('div', { style: { width: '160px', minWidth: '120px' } }, 'Location'));
+    header.appendChild(h('div', { style: { flex: 1 } }, 'Hotness'));
+    header.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } }, 'Status'));
+    header.appendChild(h('div', { style: { width: '50px', textAlign: 'right' } }, 'Count'));
+    tableWrap.appendChild(header);
 
-    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column' } });
 
     allHotspots.forEach(hs => {
       const st = getStatus(hs.max_hotness);
@@ -5432,7 +5443,7 @@ const HeatmapView = {
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -5459,9 +5470,8 @@ const HeatmapView = {
       rows.appendChild(row);
     });
 
-    main.appendChild(rows);
-    wrap.appendChild(main);
-    container.appendChild(wrap);
+    tableWrap.appendChild(rows);
+    container.appendChild(tableWrap);
   },
 };
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 96cff8fc87a80..73d22f6f1fcfc 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1326,28 +1326,39 @@ const HeatmapView = {
       return { label: 'Low', color: '#5DB8A8' };
     };
 
-    const wrap = h('div', { style: { display: 'flex', gap: '16px' } });
-
-    const stats = h('div', { style: { width: '180px', minWidth: '180px', flexShrink: 0 } });
-    stats.appendChild(h('div', { style: { fontSize: '14px', fontWeight: '600', marginBottom: '12px', color: 'var(--fg)' } }, 'Snapshot Stats'));
-    const statItems = [
-      { label: 'Total Hotspots', value: total },
-      { label: 'With Hotness', value: withHotness },
-      { label: 'Critical', value: allHotspots.filter(h => getStatus(h.max_hotness).label === 'Critical').length },
-    ];
-    statItems.forEach(s => {
-      stats.appendChild(h('div', { style: { marginBottom: '10px', padding: '8px 10px', background: 'var(--bg2)', borderRadius: '6px' } },
-        h('div', { style: { fontSize: '18px', fontWeight: '700', color: 'var(--fg)' } }, String(s.value)),
-        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '2px' } }, s.label)
+    const statusCounts = { Critical: 0, High: 0, Medium: 0, Low: 0 };
+    allHotspots.forEach(h => { statusCounts[getStatus(h.max_hotness).label]++; });
+
+    container.appendChild(h('h2', { style: { margin: '0 0 12px' } }, 'Hotspots Analysis'));
+
+    const statsRow = h('div', { style: { display: 'flex', gap: '12px', marginBottom: '20px' } });
+    [
+      { label: 'Total Hotspots', value: total, color: 'var(--fg)' },
+      { label: 'With Hotness', value: withHotness, color: 'var(--fg)' },
+      { label: 'Critical', value: statusCounts.Critical, color: '#E06C75' },
+      { label: 'High', value: statusCounts.High, color: '#D4A574' },
+      { label: 'Medium', value: statusCounts.Medium, color: '#E5C07B' },
+      { label: 'Low', value: statusCounts.Low, color: '#5DB8A8' },
+    ].forEach(s => {
+      statsRow.appendChild(h('div', { style: { flex: 1, padding: '10px 14px', background: 'var(--bg2)', borderRadius: '8px', textAlign: 'center' } },
+        h('div', { style: { fontSize: '20px', fontWeight: '700', color: s.color } }, String(s.value)),
+        h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '4px', fontWeight: '500' } }, s.label)
       ));
     });
-    wrap.appendChild(stats);
+    container.appendChild(statsRow);
+
+    const tableWrap = h('div', { style: { background: 'var(--bg2)', borderRadius: '8px', overflow: 'hidden' } });
 
-    const main = h('div', { style: { flex: 1, minWidth: 0 } });
-    main.appendChild(h('h2', { style: { margin: '0 0 4px' } }, 'Hotspots Analysis'));
-    main.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginBottom: '16px' } }, `Performance-critical locations sorted by hotness (${total} total)`));
+    const header = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', background: 'var(--bg3)', fontSize: '11px', fontWeight: '600', color: 'var(--fg3)', textTransform: 'uppercase', letterSpacing: '0.5px' } });
+    header.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } }, ''));
+    header.appendChild(h('div', { style: { width: '200px', minWidth: '160px' } }, 'Function'));
+    header.appendChild(h('div', { style: { width: '160px', minWidth: '120px' } }, 'Location'));
+    header.appendChild(h('div', { style: { flex: 1 } }, 'Hotness'));
+    header.appendChild(h('div', { style: { width: '70px', textAlign: 'center' } }, 'Status'));
+    header.appendChild(h('div', { style: { width: '50px', textAlign: 'right' } }, 'Count'));
+    tableWrap.appendChild(header);
 
-    const rows = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '6px' } });
+    const rows = h('div', { style: { display: 'flex', flexDirection: 'column' } });
 
     allHotspots.forEach(hs => {
       const st = getStatus(hs.max_hotness);
@@ -1355,7 +1366,7 @@ const HeatmapView = {
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', background: 'var(--bg2)', borderRadius: '6px', fontSize: '12px' } });
+      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -1382,9 +1393,8 @@ const HeatmapView = {
       rows.appendChild(row);
     });
 
-    main.appendChild(rows);
-    wrap.appendChild(main);
-    container.appendChild(wrap);
+    tableWrap.appendChild(rows);
+    container.appendChild(tableWrap);
   },
 };
 

>From 47854c64f118e375912d072a6d7bf19ef1744981 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 2 Aug 2026 17:27:56 +0530
Subject: [PATCH 35/41] [llvm-advisor] auto-infer source root from remark file
 paths and handle missing source gracefully in Code Explorer

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/CLI/CLIHandler.cpp             |  5 --
 .../src/Client/HTTP/Assets/bundled.html       | 27 +++++++--
 .../src/Client/HTTP/Assets/index_html.inc     | 27 +++++++--
 .../src/Client/HTTP/Assets/views.js           | 27 +++++++--
 .../llvm-advisor/src/Core/CaptureCore.cpp     | 57 ++++++++++++++++++-
 5 files changed, 121 insertions(+), 22 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
index 7e4f19c7947af..d232dd9991efc 100644
--- a/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/CLI/CLIHandler.cpp
@@ -700,11 +700,6 @@ int CLIHandler::run(int argc, char **argv) {
     SmallVector<std::string, 4> Caps(ImportCapabilities.begin(),
                                      ImportCapabilities.end());
     std::string SrcRoot = ImportSourceRoot.getValue();
-    if (SrcRoot.empty()) {
-      SmallString<256> CWD;
-      sys::fs::current_path(CWD);
-      SrcRoot = CWD.str().str();
-    }
     Expected<SnapshotRecord> Snap =
         (*Client)->importRemarks(Paths, SrcRoot, Caps);
     if (!Snap)
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 11f86727e8504..2d172ff6e6ebe 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -5596,11 +5596,22 @@
     ]);
 
     this._mainEl.innerHTML = '';
-    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
-
-    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._sourceLines = srcRes.ok ? (srcRes.data.content || '').split('\n') : [];
     this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
     this._remarkCount.textContent = `${this._remarks.length} remarks`;
+
+    if (!srcRes.ok && !this._remarks.length) {
+      this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found and no remarks available.'));
+      return;
+    }
+
+    if (!srcRes.ok) {
+      const warn = h('div', { style: { padding: '8px 12px', background: 'rgba(224,108,117,0.1)', color: '#E06C75', fontSize: '12px', borderRadius: '4px', marginBottom: '8px' } },
+        h('span', { style: { fontWeight: '600' } }, 'Source unavailable: '), 'Only remarks are shown — the original source file was not found.'
+      );
+      this._mainEl.appendChild(warn);
+    }
+
     this._renderSource();
   },
 
@@ -5636,14 +5647,20 @@
     container.appendChild(header);
 
     const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
-    lines.forEach((line, i) => {
-      const ln = i + 1;
+
+    // Determine which lines to render: either all source lines, or just lines that have remarks
+    const maxLine = lines.length;
+    const remarkLines = Object.keys(remarksByLine).map(Number).sort((a, b) => a - b);
+    const allLines = lines.length > 0 ? Array.from({ length: maxLine }, (_, i) => i + 1) : remarkLines;
+
+    allLines.forEach(ln => {
       const rems = remarksByLine[ln];
       const has = rems && rems.length > 0;
       const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
       const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
       if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
 
+      const line = lines.length > 0 ? (lines[ln - 1] || ' ') : '';
       const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
       const row = h('div', { style: rowStyle },
         h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 8a3aca87982cf..8e1768d700bf7 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -5599,11 +5599,22 @@ const CodeExplorerView = {
     ]);
 
     this._mainEl.innerHTML = '';
-    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
-
-    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._sourceLines = srcRes.ok ? (srcRes.data.content || '').split('\n') : [];
     this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
     this._remarkCount.textContent = `${this._remarks.length} remarks`;
+
+    if (!srcRes.ok && !this._remarks.length) {
+      this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found and no remarks available.'));
+      return;
+    }
+
+    if (!srcRes.ok) {
+      const warn = h('div', { style: { padding: '8px 12px', background: 'rgba(224,108,117,0.1)', color: '#E06C75', fontSize: '12px', borderRadius: '4px', marginBottom: '8px' } },
+        h('span', { style: { fontWeight: '600' } }, 'Source unavailable: '), 'Only remarks are shown — the original source file was not found.'
+      );
+      this._mainEl.appendChild(warn);
+    }
+
     this._renderSource();
   },
 
@@ -5639,14 +5650,20 @@ const CodeExplorerView = {
     container.appendChild(header);
 
     const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
-    lines.forEach((line, i) => {
-      const ln = i + 1;
+
+    // Determine which lines to render: either all source lines, or just lines that have remarks
+    const maxLine = lines.length;
+    const remarkLines = Object.keys(remarksByLine).map(Number).sort((a, b) => a - b);
+    const allLines = lines.length > 0 ? Array.from({ length: maxLine }, (_, i) => i + 1) : remarkLines;
+
+    allLines.forEach(ln => {
       const rems = remarksByLine[ln];
       const has = rems && rems.length > 0;
       const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
       const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
       if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
 
+      const line = lines.length > 0 ? (lines[ln - 1] || ' ') : '';
       const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
       const row = h('div', { style: rowStyle },
         h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 73d22f6f1fcfc..17bd4890d8422 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1522,11 +1522,22 @@ const CodeExplorerView = {
     ]);
 
     this._mainEl.innerHTML = '';
-    if (!srcRes.ok) { this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found')); return; }
-
-    this._sourceLines = (srcRes.data.content || '').split('\n');
+    this._sourceLines = srcRes.ok ? (srcRes.data.content || '').split('\n') : [];
     this._remarks = (remRes.ok && remRes.data) ? remRes.data.remarks || [] : [];
     this._remarkCount.textContent = `${this._remarks.length} remarks`;
+
+    if (!srcRes.ok && !this._remarks.length) {
+      this._mainEl.appendChild(h('div', { style: { padding: '12px' } }, 'Source file not found and no remarks available.'));
+      return;
+    }
+
+    if (!srcRes.ok) {
+      const warn = h('div', { style: { padding: '8px 12px', background: 'rgba(224,108,117,0.1)', color: '#E06C75', fontSize: '12px', borderRadius: '4px', marginBottom: '8px' } },
+        h('span', { style: { fontWeight: '600' } }, 'Source unavailable: '), 'Only remarks are shown — the original source file was not found.'
+      );
+      this._mainEl.appendChild(warn);
+    }
+
     this._renderSource();
   },
 
@@ -1562,14 +1573,20 @@ const CodeExplorerView = {
     container.appendChild(header);
 
     const codeWrap = h('div', { style: { fontFamily: 'monospace', fontSize: '13px', lineHeight: '20px' } });
-    lines.forEach((line, i) => {
-      const ln = i + 1;
+
+    // Determine which lines to render: either all source lines, or just lines that have remarks
+    const maxLine = lines.length;
+    const remarkLines = Object.keys(remarksByLine).map(Number).sort((a, b) => a - b);
+    const allLines = lines.length > 0 ? Array.from({ length: maxLine }, (_, i) => i + 1) : remarkLines;
+
+    allLines.forEach(ln => {
       const rems = remarksByLine[ln];
       const has = rems && rems.length > 0;
       const color = has ? (TYPE_COLORS[rems[0].type] || 'var(--teal)') : '';
       const rowStyle = { display: 'flex', padding: '0 8px', minHeight: '20px' };
       if (has) { rowStyle.background = TYPE_BG[rems[0].type] || 'rgba(123,224,214,0.06)'; rowStyle.cursor = 'pointer'; }
 
+      const line = lines.length > 0 ? (lines[ln - 1] || ' ') : '';
       const badge = has ? h('span', { style: { marginLeft: '8px', fontSize: '10px', padding: '0 4px', borderRadius: '3px', background: color, color: 'var(--bg)', fontWeight: '600' } }, String(rems.length)) : null;
       const row = h('div', { style: rowStyle },
         h('span', { style: { width: '44px', textAlign: 'right', paddingRight: '10px', userSelect: 'none', color: has ? color : 'var(--text-muted)', flexShrink: '0' } }, String(ln)),
diff --git a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
index 9186434b3f0da..31a42633e9aca 100644
--- a/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
+++ b/llvm/tools/llvm-advisor/src/Core/CaptureCore.cpp
@@ -25,6 +25,49 @@ using namespace llvm::advisor;
 
 namespace {
 
+/// Infer a source root by scanning the first N remarks and finding the longest
+/// common directory prefix of their source file paths. Returns an empty string
+/// if no common prefix is found or if paths are relative.
+static std::string inferSourceRootFromRemarks(StringRef Path) {
+  SmallVector<std::string, 32> SourcePaths;
+  if (Error E = foreachRemark(Path, [&](const remarks::Remark &R) -> Error {
+        if (R.Loc && !R.Loc->SourceFilePath.empty())
+          SourcePaths.push_back(R.Loc->SourceFilePath.str());
+        if (SourcePaths.size() >= 50)
+          return createStringError(inconvertibleErrorCode(), "sampled");
+        return Error::success();
+      })) {
+    consumeError(std::move(E));
+  }
+
+  if (SourcePaths.empty())
+    return "";
+
+  // Find longest common directory prefix
+  std::string Prefix = sys::path::parent_path(SourcePaths[0]).str();
+  for (size_t I = 1; I < SourcePaths.size() && !Prefix.empty(); ++I) {
+    std::string Parent = sys::path::parent_path(SourcePaths[I]).str();
+    size_t Len = std::min(Prefix.size(), Parent.size());
+    size_t Common = 0;
+    for (size_t J = 0; J < Len; ++J) {
+      if (Prefix[J] != Parent[J])
+        break;
+      Common = J + 1;
+    }
+    Prefix = Prefix.substr(0, Common);
+    // Trim to last directory separator
+    size_t LastSep = Prefix.find_last_of("/\\");
+    if (LastSep != std::string::npos)
+      Prefix = Prefix.substr(0, LastSep);
+  }
+
+  // Only use absolute paths as roots
+  if (!Prefix.empty() && sys::path::is_absolute(Prefix))
+    return Prefix;
+
+  return "";
+}
+
 // Capability categories used to determine which artifacts must be synthesized.
 constexpr StringLiteral IRCapabilities[] = {
     "llvm.ir.summary",     "llvm.ir.function_stats",
@@ -307,10 +350,20 @@ CaptureCore::importRemarks(ArrayRef<std::string> RemarkPaths,
                      std::chrono::system_clock::now().time_since_epoch())
                      .count();
 
+  // If no source root was provided, try to infer it from the first remark file.
+  std::string InferredRoot = SourceRoot.str();
+  if (InferredRoot.empty() && !RemarkPaths.empty()) {
+    InferredRoot = inferSourceRootFromRemarks(RemarkPaths[0]);
+  }
+  // Fallback: use the parent directory of the first remark file.
+  if (InferredRoot.empty() && !RemarkPaths.empty()) {
+    InferredRoot = sys::path::parent_path(RemarkPaths[0]).str();
+  }
+
   SnapshotRecord Snapshot;
-  Snapshot.SourceRoot = SourceRoot.str();
+  Snapshot.SourceRoot = InferredRoot;
   Snapshot.CreatedUnix = Now;
-  Snapshot.ID = computeSnapshotID(SourceRoot, "imported", Now);
+  Snapshot.ID = computeSnapshotID(InferredRoot, "imported", Now);
   if (Error Err = Storage.metadata().putSnapshot(Snapshot))
     return std::move(Err);
 

>From 5827b0e7ac2efadb41207344f8de3a6d371b2abf Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 15 Aug 2026 15:20:08 +0530
Subject: [PATCH 36/41] [llvm-advisor] open Code Explorer filtered to the
 function from heatmap rows

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html       | 28 ++++++++++++++++---
 .../src/Client/HTTP/Assets/core.js            |  1 +
 .../src/Client/HTTP/Assets/index_html.inc     | 28 ++++++++++++++++---
 .../src/Client/HTTP/Assets/views.js           | 27 +++++++++++++++---
 .../src/Client/HTTP/HTTPServer.cpp            | 16 ++++++++---
 5 files changed, 84 insertions(+), 16 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 2d172ff6e6ebe..47bf2bcbe6b01 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -856,6 +856,7 @@
     if (filters) {
       if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
       if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.function) url += `&function=${encodeURIComponent(filters.function)}`;
       if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
     }
     return API.get(url);
@@ -5440,7 +5441,20 @@
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
+      const canOpen = !!hs.file;
+      const row = h('div', {
+        style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)', cursor: canOpen ? 'pointer' : 'default' },
+        title: canOpen ? `Click to open ${hs.function || 'this function'} in Code Explorer` : 'No source location for this hotspot',
+        onClick: canOpen ? () => {
+          const qs = new URLSearchParams();
+          qs.set('path', hs.file);
+          if (hs.line > 0) qs.set('line', String(hs.line));
+          if (hs.function) qs.set('function', hs.function);
+          Router.navigate(`/explorer?${qs.toString()}`);
+        } : null,
+        onMouseEnter: (e) => { if (canOpen) e.currentTarget.style.background = 'var(--bg3)'; },
+        onMouseLeave: (e) => { if (canOpen) e.currentTarget.style.background = ''; },
+      });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -5479,7 +5493,7 @@
 const CodeExplorerView = {
   _snap: null,
   _mainEl: null,
-  _filters: { pass: '', name: '', type: '' },
+  _filters: { pass: '', name: '', type: '', function: '' },
 
   async render() {
     const container = h('div', {});
@@ -5537,6 +5551,7 @@
     const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
     const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
     const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const funcInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter function...', style: { width: '140px' } });
     const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
     ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
       const enumVal = [1, 2, 3, 6][idx];
@@ -5549,13 +5564,14 @@
       typeChips.appendChild(chip);
     });
     const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
-    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(funcInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
     mainCol.appendChild(filterBar);
 
     let debounce = null;
-    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; this._filters.function = funcInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
     passInput.addEventListener('input', onFilter);
     nameInput.addEventListener('input', onFilter);
+    funcInput.addEventListener('input', onFilter);
 
     this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
     this._remarkCount = remarkCount;
@@ -5575,6 +5591,10 @@
       nameInput.value = params.name;
       this._filters.name = params.name;
     }
+    if (params.function) {
+      funcInput.value = params.function;
+      this._filters.function = params.function;
+    }
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index bbe2361777ba8..f85d22315b176 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -119,6 +119,7 @@ const API = {
     if (filters) {
       if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
       if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.function) url += `&function=${encodeURIComponent(filters.function)}`;
       if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
     }
     return API.get(url);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 8e1768d700bf7..bddbb0017f80e 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -859,6 +859,7 @@ const API = {
     if (filters) {
       if (filters.pass) url += `&pass=${encodeURIComponent(filters.pass)}`;
       if (filters.name) url += `&name=${encodeURIComponent(filters.name)}`;
+      if (filters.function) url += `&function=${encodeURIComponent(filters.function)}`;
       if (filters.type != null && filters.type !== '') url += `&type=${filters.type}`;
     }
     return API.get(url);
@@ -5443,7 +5444,20 @@ const HeatmapView = {
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
+      const canOpen = !!hs.file;
+      const row = h('div', {
+        style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)', cursor: canOpen ? 'pointer' : 'default' },
+        title: canOpen ? `Click to open ${hs.function || 'this function'} in Code Explorer` : 'No source location for this hotspot',
+        onClick: canOpen ? () => {
+          const qs = new URLSearchParams();
+          qs.set('path', hs.file);
+          if (hs.line > 0) qs.set('line', String(hs.line));
+          if (hs.function) qs.set('function', hs.function);
+          Router.navigate(`/explorer?${qs.toString()}`);
+        } : null,
+        onMouseEnter: (e) => { if (canOpen) e.currentTarget.style.background = 'var(--bg3)'; },
+        onMouseLeave: (e) => { if (canOpen) e.currentTarget.style.background = ''; },
+      });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -5482,7 +5496,7 @@ const HeatmapView = {
 const CodeExplorerView = {
   _snap: null,
   _mainEl: null,
-  _filters: { pass: '', name: '', type: '' },
+  _filters: { pass: '', name: '', type: '', function: '' },
 
   async render() {
     const container = h('div', {});
@@ -5540,6 +5554,7 @@ const CodeExplorerView = {
     const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
     const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
     const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const funcInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter function...', style: { width: '140px' } });
     const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
     ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
       const enumVal = [1, 2, 3, 6][idx];
@@ -5552,13 +5567,14 @@ const CodeExplorerView = {
       typeChips.appendChild(chip);
     });
     const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
-    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(funcInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
     mainCol.appendChild(filterBar);
 
     let debounce = null;
-    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; this._filters.function = funcInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
     passInput.addEventListener('input', onFilter);
     nameInput.addEventListener('input', onFilter);
+    funcInput.addEventListener('input', onFilter);
 
     this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
     this._remarkCount = remarkCount;
@@ -5578,6 +5594,10 @@ const CodeExplorerView = {
       nameInput.value = params.name;
       this._filters.name = params.name;
     }
+    if (params.function) {
+      funcInput.value = params.function;
+      this._filters.function = params.function;
+    }
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 17bd4890d8422..045ff95b2e17e 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1366,7 +1366,20 @@ const HeatmapView = {
       const file = (hs.file || '').split('/').pop() || 'unknown';
       const loc = hs.line > 0 ? `${file}:${hs.line}` : file;
 
-      const row = h('div', { style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)' } });
+      const canOpen = !!hs.file;
+      const row = h('div', {
+        style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '8px 12px', fontSize: '12px', borderBottom: '1px solid var(--border)', cursor: canOpen ? 'pointer' : 'default' },
+        title: canOpen ? `Click to open ${hs.function || 'this function'} in Code Explorer` : 'No source location for this hotspot',
+        onClick: canOpen ? () => {
+          const qs = new URLSearchParams();
+          qs.set('path', hs.file);
+          if (hs.line > 0) qs.set('line', String(hs.line));
+          if (hs.function) qs.set('function', hs.function);
+          Router.navigate(`/explorer?${qs.toString()}`);
+        } : null,
+        onMouseEnter: (e) => { if (canOpen) e.currentTarget.style.background = 'var(--bg3)'; },
+        onMouseLeave: (e) => { if (canOpen) e.currentTarget.style.background = ''; },
+      });
 
       row.appendChild(h('div', { style: { width: '28px', textAlign: 'center' } },
         h('span', { style: { display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', background: st.color } })
@@ -1405,7 +1418,7 @@ const HeatmapView = {
 const CodeExplorerView = {
   _snap: null,
   _mainEl: null,
-  _filters: { pass: '', name: '', type: '' },
+  _filters: { pass: '', name: '', type: '', function: '' },
 
   async render() {
     const container = h('div', {});
@@ -1463,6 +1476,7 @@ const CodeExplorerView = {
     const filterBar = h('div', { style: { display: 'flex', gap: '6px', marginBottom: '6px', flexWrap: 'wrap', alignItems: 'center' } });
     const passInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter pass...', style: { width: '120px' } });
     const nameInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter remark...', style: { width: '120px' } });
+    const funcInput = h('input', { class: 'triage-input', type: 'search', placeholder: 'filter function...', style: { width: '140px' } });
     const typeChips = h('div', { style: { display: 'flex', gap: '4px' } });
     ['passed', 'missed', 'analysis', 'failure'].forEach((t, idx) => {
       const enumVal = [1, 2, 3, 6][idx];
@@ -1475,13 +1489,14 @@ const CodeExplorerView = {
       typeChips.appendChild(chip);
     });
     const remarkCount = h('span', { class: 'text-muted', style: { fontSize: '11px', marginLeft: 'auto' } }, '');
-    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
+    filterBar.appendChild(passInput); filterBar.appendChild(nameInput); filterBar.appendChild(funcInput); filterBar.appendChild(typeChips); filterBar.appendChild(remarkCount);
     mainCol.appendChild(filterBar);
 
     let debounce = null;
-    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
+    const onFilter = () => { this._filters.pass = passInput.value; this._filters.name = nameInput.value; this._filters.function = funcInput.value; clearTimeout(debounce); debounce = setTimeout(() => this._reloadRemarks(), 300); };
     passInput.addEventListener('input', onFilter);
     nameInput.addEventListener('input', onFilter);
+    funcInput.addEventListener('input', onFilter);
 
     this._mainEl = h('div', { style: { flex: '1', overflow: 'auto', border: '1px solid var(--border)', borderRadius: '6px', background: 'var(--bg)' } });
     this._remarkCount = remarkCount;
@@ -1501,6 +1516,10 @@ const CodeExplorerView = {
       nameInput.value = params.name;
       this._filters.name = params.name;
     }
+    if (params.function) {
+      funcInput.value = params.function;
+      this._filters.function = params.function;
+    }
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index 37455546c01db..b033914482590 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -985,7 +985,9 @@ static HTTPResult handleGetSource(CoreClient &Client, StringRef SnapID,
 
 static HTTPResult handleGetSourceRemarks(CoreClient &Client, StringRef SnapID,
                                          StringRef FilePath, StringRef FilterPass,
-                                         StringRef FilterName, int64_t FilterType) {
+                                         StringRef FilterName,
+                                         StringRef FilterFunction,
+                                         int64_t FilterType) {
   if (FilePath.empty())
     return makeJSONErrorStr(400, "path parameter is required");
 
@@ -1055,6 +1057,10 @@ static HTTPResult handleGetSourceRemarks(CoreClient &Client, StringRef SnapID,
             if (!FilterName.empty() && !NameStr.contains_insensitive(FilterName)) continue;
 
             int64_t FI = (*FuncCol)[I].getAsInteger().value_or(-1);
+            StringRef FuncStr = FI >= 0 && FI < (int64_t)FuncStrs->size()
+                ? (*FuncStrs)[FI].getAsString().value_or("") : "";
+            if (!FilterFunction.empty() &&
+                !FuncStr.contains_insensitive(FilterFunction)) continue;
             JOS.object([&] {
               JOS.attribute("line", (*LineCol)[I].getAsInteger().value_or(-1));
               JOS.attribute("column", (*ColumnCol)[I].getAsInteger().value_or(-1));
@@ -1064,7 +1070,7 @@ static HTTPResult handleGetSourceRemarks(CoreClient &Client, StringRef SnapID,
               int64_t H = (*HotnessCol)[I].getAsInteger().value_or(-1);
               if (H >= 0) JOS.attribute("hotness", H);
               if (FI >= 0 && FI < (int64_t)FuncStrs->size())
-                JOS.attribute("function", (*FuncStrs)[FI].getAsString().value_or(""));
+                JOS.attribute("function", FuncStr);
             });
             ++Count;
           }
@@ -1710,18 +1716,20 @@ Error llvm::advisor::HTTPServer::run() {
           if (PathIt == QueryParams.end() || SnapIt == QueryParams.end())
             Res = makeJSONErrorStr(400, "path and snapshot_id required");
           else {
-            StringRef FPass, FName;
+            StringRef FPass, FName, FFunc;
             int64_t FType = -1;
             auto PIt = QueryParams.find("pass");
             if (PIt != QueryParams.end()) FPass = PIt->second;
             auto NIt = QueryParams.find("name");
             if (NIt != QueryParams.end()) FName = NIt->second;
+            auto FIt = QueryParams.find("function");
+            if (FIt != QueryParams.end()) FFunc = FIt->second;
             auto TIt = QueryParams.find("type");
             if (TIt != QueryParams.end())
               StringRef(TIt->second).getAsInteger(10, FType);
             Res = handleGetSourceRemarks(
                 Client, resolveSnapshotHTTP(Client, SnapIt->second),
-                PathIt->second, FPass, FName, FType);
+                PathIt->second, FPass, FName, FFunc, FType);
           }
         } else if (Path == "/api/v1/source") {
           auto PathIt = QueryParams.find("path");

>From 5ae7a690bf8d1d50a8fcf3f9114071c5f1dbb98f Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 15 Aug 2026 19:23:47 +0530
Subject: [PATCH 37/41] [llvm-advisor] reset Code Explorer filters on each
 render

Signed-off-by: kamini08 <kaminibanait03 at gmail.com>
---
 .../src/Client/HTTP/Assets/bundled.html          | 16 ++++------------
 .../src/Client/HTTP/Assets/index_html.inc        | 16 ++++------------
 .../llvm-advisor/src/Client/HTTP/Assets/views.js | 16 ++++------------
 3 files changed, 12 insertions(+), 36 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 47bf2bcbe6b01..e8ccbb220b346 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -5583,18 +5583,10 @@
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    if (params.pass) {
-      passInput.value = params.pass;
-      this._filters.pass = params.pass;
-    }
-    if (params.name) {
-      nameInput.value = params.name;
-      this._filters.name = params.name;
-    }
-    if (params.function) {
-      funcInput.value = params.function;
-      this._filters.function = params.function;
-    }
+    this._filters = { pass: params.pass || '', name: params.name || '', type: '', function: params.function || '' };
+    passInput.value = this._filters.pass;
+    nameInput.value = this._filters.name;
+    funcInput.value = this._filters.function;
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index bddbb0017f80e..52cb1276a0ee6 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -5586,18 +5586,10 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    if (params.pass) {
-      passInput.value = params.pass;
-      this._filters.pass = params.pass;
-    }
-    if (params.name) {
-      nameInput.value = params.name;
-      this._filters.name = params.name;
-    }
-    if (params.function) {
-      funcInput.value = params.function;
-      this._filters.function = params.function;
-    }
+    this._filters = { pass: params.pass || '', name: params.name || '', type: '', function: params.function || '' };
+    passInput.value = this._filters.pass;
+    nameInput.value = this._filters.name;
+    funcInput.value = this._filters.function;
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 045ff95b2e17e..9bdf9bd2671da 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1508,18 +1508,10 @@ const CodeExplorerView = {
     const initialPath = params.path || (files.length > 0 ? files[0].path : null);
     this._scrollToLine = params.line ? parseInt(params.line, 10) : 0;
 
-    if (params.pass) {
-      passInput.value = params.pass;
-      this._filters.pass = params.pass;
-    }
-    if (params.name) {
-      nameInput.value = params.name;
-      this._filters.name = params.name;
-    }
-    if (params.function) {
-      funcInput.value = params.function;
-      this._filters.function = params.function;
-    }
+    this._filters = { pass: params.pass || '', name: params.name || '', type: '', function: params.function || '' };
+    passInput.value = this._filters.pass;
+    nameInput.value = this._filters.name;
+    funcInput.value = this._filters.function;
 
     if (initialPath) {
       const match = list.querySelector(`.explorer-file[data-path="${CSS.escape(initialPath)}"]`);

>From 6598827463ad7051a5004b86f1e2705a3f11be5d Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 22 Aug 2026 03:16:53 +0530
Subject: [PATCH 38/41] [llvm-advisor] Drop placeholder mix/size_diff
 capabilities and fix registry

---
 .../config/capabilities/catalog.json          | 22 -------------------
 .../src/Capability/CapabilityRegistry.cpp     |  6 -----
 2 files changed, 28 deletions(-)

diff --git a/llvm/tools/llvm-advisor/config/capabilities/catalog.json b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
index 5f7ffb8e06219..0c75bf9558770 100644
--- a/llvm/tools/llvm-advisor/config/capabilities/catalog.json
+++ b/llvm/tools/llvm-advisor/config/capabilities/catalog.json
@@ -9,28 +9,6 @@
       "readiness": "L1",
       "dependencies": []
     },
-    {
-      "id": "llvm.remarks.instruction_mix",
-      "name": "Remarks instruction mix",
-      "version": "1",
-      "runner": "builtin.remarks_mix",
-      "summary": "instruction mix requires parsed optimization remarks",
-      "readiness": "L1",
-      "dependencies": [
-        "llvm.remarks.summary"
-      ]
-    },
-    {
-      "id": "llvm.remarks.size_diff",
-      "name": "Remarks size diff",
-      "version": "1",
-      "runner": "builtin.remarks_size_diff",
-      "summary": "size diff requires comparable remarks inputs",
-      "readiness": "L1",
-      "dependencies": [
-        "llvm.remarks.summary"
-      ]
-    },
     {
       "id": "llvm.remarks.relational",
       "name": "Optimization remarks relational view",
diff --git a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
index 4c98f7c64b7a5..8b74f5d79a9e3 100644
--- a/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
+++ b/llvm/tools/llvm-advisor/src/Capability/CapabilityRegistry.cpp
@@ -12,9 +12,7 @@
 
 #include "Capability/CapabilityRegistry.h"
 #include "Analysis/IR/RemarksAnalyzer.h"
-#include "Analysis/IR/RemarksMixAnalyzer.h"
 #include "Analysis/IR/RemarksRelationalAnalyzer.h"
-#include "Analysis/IR/RemarksSizeDiffAnalyzer.h"
 #include "Analysis/IR/RemarksHotspotAnalyzer.h"
 #include "Analysis/Inspection/RemarksDetailAnalyzer.h"
 #include "Utils/JSON.h"
@@ -223,10 +221,6 @@ CapabilityRegistry::createDeclarativeRunner(const CapabilitySpec &Spec) const {
 void CapabilityRegistry::addBuiltinRunners() {
   consumeError(addRunner("builtin.remarks_summary",
                          std::make_unique<RemarksAnalyzer>()));
-  consumeError(addRunner("builtin.remarks_mix",
-                         std::make_unique<RemarksMixAnalyzer>()));
-  consumeError(addRunner("builtin.remarks_size_diff",
-                         std::make_unique<RemarksSizeDiffAnalyzer>()));
   consumeError(addRunner("builtin.remarks_relational",
                          std::make_unique<RemarksRelationalAnalyzer>()));
   consumeError(addRunner("builtin.remarks_hotspot",

>From c2ac0bfe6429529262396d45d032b816a61ec780 Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 22 Aug 2026 03:35:20 +0530
Subject: [PATCH 39/41] [llvm-advisor] Strip non-remarks UI views and
 capability references from user branch

---
 .../src/Client/HTTP/Assets/bundle.py          |   2 -
 .../src/Client/HTTP/Assets/bundled.html       | 885 +-----------------
 .../src/Client/HTTP/Assets/compare.js         |   3 +-
 .../src/Client/HTTP/Assets/core.js            |  11 +-
 .../src/Client/HTTP/Assets/index.html         |   2 -
 .../src/Client/HTTP/Assets/index_html.inc     | 885 +-----------------
 .../src/Client/HTTP/Assets/overview.js        |   5 +-
 .../src/Client/HTTP/Assets/shell.js           |   4 -
 .../src/Client/HTTP/Assets/unit-detail.js     | 150 +--
 .../src/Client/HTTP/Assets/views.js           | 710 --------------
 10 files changed, 18 insertions(+), 2639 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
index 49fb3e9a69fbf..f138ab6a909d1 100755
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundle.py
@@ -67,8 +67,6 @@ def main():
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
-      Router.register('/timeline', () => TimelineView.render());
-      Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/explorer', () => CodeExplorerView.render());
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index e8ccbb220b346..9a43eb2e7afd8 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -745,8 +745,6 @@
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
-  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
-  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
@@ -861,17 +859,10 @@
     }
     return API.get(url);
   },
-  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
-  insight: (snapId, name, baseline) => {
-    let url = `/snapshots/${snapId}/insights/${name}`;
-    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
-    return API.get(url);
-  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
   compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
-  jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
     let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
     if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
@@ -991,7 +982,7 @@
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2199,8 +2190,6 @@
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
-      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
-      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
@@ -2328,8 +2317,6 @@
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
-    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
-    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
@@ -2452,10 +2439,7 @@
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary',
-                      'llvm.debug.summary', 'clang.ast.summary',
-                      'llvm.lto.summary', 'llvm.lto.function_stats'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
@@ -3257,7 +3241,7 @@
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
+    const tabs = ['Overview', 'Remarks', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -3301,76 +3285,6 @@
     );
   },
 
-  openFunctionExplorer(unit, snapshotId, functionName) {
-    const container = document.getElementById('inline-explorer');
-    if (!container) return;
-    clearEl(container);
-
-    const card = h('div', { class: 'inline-explorer' });
-    const header = h('div', { class: 'inline-explorer-header' },
-      h('span', { class: 'capability-card-title mono' }, functionName),
-      h('button', {
-        class: 'detail-card-close',
-        onClick: () => clearEl(container),
-        title: 'Close'
-      }, '×')
-    );
-
-    const controls = h('div', { class: 'cap-pills' });
-    const body = h('div', { class: 'capability-stack' });
-    const modes = [
-      ['signals', 'Signals'],
-      ['ir', 'IR'],
-      ['cfg', 'CFG'],
-      ['dom', 'Dom'],
-      ['loop', 'Loops'],
-      ['callgraph', 'Call Graph'],
-      ['asm', 'Asm'],
-      ['mca', 'MCA'],
-      ['remarks', 'Remarks'],
-      ['debug', 'Debug'],
-      ['passes', 'Passes'],
-    ];
-
-    const loadMode = async (mode, pill) => {
-      Array.from(controls.children).forEach(node => node.classList.remove('available'));
-      if (pill) pill.classList.add('available');
-      clearEl(body);
-      body.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, `Loading ${mode}`),
-        h('div', { class: 'reason mono' }, functionName)));
-      const res = await API.inspect(mode, {
-        snapshot_id: snapshotId,
-        unit: unit.id,
-        function: functionName,
-      });
-      clearEl(body);
-      if (!res.ok) {
-        body.appendChild(h('div', { class: 'empty-state' },
-          h('div', {}, 'Inspection failed'),
-          h('div', { class: 'reason mono' }, res.error || 'unknown error')));
-        return;
-      }
-      body.appendChild(UI.inspectResult(res.data));
-    };
-
-    modes.forEach(([mode, label], index) => {
-      const pill = h('button', {
-        class: `cap-pill ${index === 0 ? 'available' : ''}`,
-        onClick: () => loadMode(mode, pill),
-      }, label);
-      controls.appendChild(pill);
-      if (index === 0) setTimeout(() => loadMode(mode, pill), 0);
-    });
-
-    card.appendChild(header);
-    card.appendChild(controls);
-    card.appendChild(body);
-    container.appendChild(card);
-
-    // Scroll into view
-    card.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
-  },
 
   renderCapSidebar(sidebar, unit) {
     clearEl(sidebar);
@@ -3384,29 +3298,6 @@
       h('div', { class: 'rail-title' }, 'Coverage'),
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
-    // Function list placeholder in sidebar
-    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
-      h('div', { class: 'rail-title' }, 'Functions'),
-      h('div', { class: 'rail-empty' }, 'Loading function list')
-    ));
-  },
-
-  addSection(parent, title, open, kvPairs) {
-    const section = h('div', { class: 'cap-section' + (open ? ' open' : '') });
-    const header = h('div', { class: 'cap-section-header', onClick: () => section.classList.toggle('open') },
-      h('span', {}, title)
-    );
-    const body = h('div', { class: 'cap-section-body' });
-    kvPairs.forEach(([k, v]) => {
-      body.appendChild(h('div', { class: 'kv' },
-        h('span', { class: 'k' }, k),
-        h('span', { class: 'v' }, v)
-      ));
-    });
-    section.appendChild(header);
-    section.appendChild(body);
-    parent.appendChild(section);
-  },
 
   renderTab(tab, state) {
     if (!state.results.length)
@@ -3414,20 +3305,6 @@
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
-    if (tab === 'Diagnostics') {
-      const findings = state.results
-        .filter(r => r.capability.startsWith('clang.diag'))
-        .flatMap(r => r.findings);
-      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
-      const bySev = {};
-      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
-      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
-      return h('div', { class: 'capability-stack' },
-        chartData.length ? UI.barChart(chartData) : null,
-        UI.findingList(findings)
-      );
-    }
-
     if (tab === 'Remarks') {
       const relResult = state.byCapability.get('llvm.remarks.relational');
       if (relResult && relResult.available && relResult.value && relResult.value.columns) {
@@ -3450,13 +3327,6 @@
       );
     }
 
-    if (tab === 'Functions') {
-      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
-      const rows = fnResult?.value?.functions || [];
-      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
-      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
-    }
-
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -3474,9 +3344,6 @@
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
-        this.summaryCard('Functions', metrics.functions, 'neutral'),
-        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
-        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -3500,12 +3367,9 @@
   },
 
   collectOverview(results) {
-    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
+    const metrics = { remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
-      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
-      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
-      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -3515,7 +3379,7 @@
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
+      : ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -3527,30 +3391,6 @@
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
-    // Populate function list in sidebar
-    const fnCard = sidebar.querySelector('#function-list-card');
-    results.forEach(r => {
-      const val = r.value;
-      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
-        if (fnCard) {
-          clearEl(fnCard);
-          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
-          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
-          const list = h('div', { class: 'fn-section' });
-          fns.slice(0, 50).forEach(fn => {
-            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
-              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
-              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
-            ));
-          });
-          if (fns.length > 50) {
-            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
-              `+ ${fns.length - 50} more…`));
-          }
-          fnCard.appendChild(list);
-        }
-      }
-    });
     if (refresh) refresh();
   },
 
@@ -4027,8 +3867,7 @@
 
   async _loadUnitDetail(detail, change) {
     const matchType = change.match_type || 'changed';
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.debug.summary'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
 
     const unitId = change.candidate_unit_id || change.base_unit_id;
     const snapId = change.candidate_unit_id ? this._candidateId : this._baseId;
@@ -4073,716 +3912,6 @@
 
   </script>
   <script>
-/* ============================================================
-   LLVM Advisor — Timeline View
-   ============================================================ */
-
-const TimelineView = {
-  _metrics: ['unit_count', 'instruction_count', 'health_score'],
-  _colors: {
-    unit_count: '#5B8DB8',
-    instruction_count: '#5DB8A8',
-    health_score: '#6EC9C4',
-    warning_count: '#D4A574',
-    error_count: '#D48B9B',
-  },
-  _snapData: [],
-
-  async render() {
-    const container = h('div', {});
-
-    const chips = h('div', { class: 'metric-chips' });
-    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
-      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
-      const chip = h('div', {
-        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
-        onClick: () => {
-          const idx = this._metrics.indexOf(m);
-          if (idx >= 0) this._metrics.splice(idx, 1);
-          else if (this._metrics.length < 4) this._metrics.push(m);
-          chip.classList.toggle('active');
-          this._drawChart();
-        },
-      },
-        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
-        label
-      );
-      chips.appendChild(chip);
-    });
-    container.appendChild(chips);
-
-    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
-
-    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
-
-    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
-    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
-
-    Shell.renderMain(container);
-    await this._loadData();
-  },
-
-  async _loadData() {
-    const snaps = State.get('snapshots') || [];
-    if (!snaps.length) {
-      this._renderSnapList([]);
-      return;
-    }
-
-    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
-    this._snapData = snaps.map((s, i) => {
-      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
-      return {
-        ...s,
-        unit_count: sum.unit_count ?? s.unit_count ?? 0,
-        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
-        health_score: sum.health_score ?? 0,
-        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
-        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
-        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
-        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
-      };
-    });
-
-    this._renderSnapList(this._snapData);
-    this._renderMetricCards();
-    this._drawChart();
-  },
-
-  _renderMetricCards() {
-    const el = document.getElementById('timeline-metrics');
-    if (!el || !this._snapData.length) return;
-    clearEl(el);
-    const latest = this._snapData[0];
-    const metricDefs = [
-      { key: 'unit_count', label: 'Units' },
-      { key: 'instruction_count', label: 'Instructions' },
-      { key: 'health_score', label: 'Health' },
-      { key: 'remark_count', label: 'Remarks' },
-      { key: 'function_count', label: 'Functions' },
-    ];
-    metricDefs.forEach(m => {
-      const val = latest[m.key] ?? 0;
-      let delta = null, deltaCls = 'neutral';
-      if (this._snapData.length > 1) {
-        const prev = this._snapData[1];
-        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
-        if (d !== 0) {
-          const sign = d > 0 ? '+' : '';
-          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
-          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
-          delta = `${sign}${formatNumber(d)} vs prev`;
-        }
-      }
-      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
-    });
-  },
-
-  _drawChart() {
-    const container = document.getElementById('timeline-chart-container');
-    if (!container) return;
-    clearEl(container);
-    const data = this._snapData;
-    const svgNS = 'http://www.w3.org/2000/svg';
-    const svg = document.createElementNS(svgNS, 'svg');
-    svg.style.width = '100%';
-    svg.style.height = '220px';
-    container.appendChild(svg);
-
-    if (data.length < 2) {
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
-      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
-      svg.appendChild(text);
-      return;
-    }
-
-    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
-    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
-    const chartW = w - padL - padR;
-    const chartH = ht - padT - padB;
-
-    // Horizontal grid lines
-    for (let i = 0; i <= 4; i++) {
-      const y = padT + (chartH * i / 4);
-      const line = document.createElementNS(svgNS, 'line');
-      line.setAttribute('x1', padL); line.setAttribute('y1', y);
-      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
-      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
-      line.setAttribute('stroke-width', '1');
-      svg.appendChild(line);
-    }
-
-    const xStep = chartW / (data.length - 1);
-
-    this._metrics.forEach(m => {
-      const values = data.map(s => Number(s[m]) || 0);
-      const max = Math.max(...values, 1);
-      const min = Math.min(...values, 0);
-      const range = max - min || 1;
-      const color = this._colors[m] || 'var(--accent)';
-
-      const points = data.map((_, i) => {
-        const x = padL + i * xStep;
-        const y = padT + chartH - ((values[i] - min) / range) * chartH;
-        return `${x.toFixed(1)},${y.toFixed(1)}`;
-      });
-
-      // Area fill
-      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
-      const area = document.createElementNS(svgNS, 'polygon');
-      area.setAttribute('points', areaPoints);
-      area.setAttribute('fill', color);
-      area.setAttribute('opacity', '0.08');
-      svg.appendChild(area);
-
-      const poly = document.createElementNS(svgNS, 'polyline');
-      poly.setAttribute('points', points.join(' '));
-      poly.setAttribute('fill', 'none');
-      poly.setAttribute('stroke', color);
-      poly.setAttribute('stroke-width', '2');
-      poly.setAttribute('stroke-linejoin', 'round');
-      svg.appendChild(poly);
-
-      data.forEach((_, i) => {
-        const [x, y] = points[i].split(',');
-        const circle = document.createElementNS(svgNS, 'circle');
-        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
-        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
-        svg.appendChild(circle);
-      });
-
-      // Y-axis labels for first metric only
-      if (m === this._metrics[0]) {
-        for (let i = 0; i <= 4; i++) {
-          const val = min + (range * (4 - i) / 4);
-          const y = padT + (chartH * i / 4);
-          const text = document.createElementNS(svgNS, 'text');
-          text.setAttribute('x', String(padL - 6));
-          text.setAttribute('y', String(y + 3));
-          text.setAttribute('text-anchor', 'end');
-          text.setAttribute('fill', 'var(--fg3)');
-          text.setAttribute('font-size', '9');
-          text.setAttribute('font-family', 'var(--mono)');
-          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
-          svg.appendChild(text);
-        }
-      }
-    });
-
-    // X-axis labels
-    data.forEach((s, i) => {
-      const x = padL + i * xStep;
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = (s.id || '').slice(0, 6);
-      svg.appendChild(text);
-    });
-
-    // Legend
-    const legendX = w - padR - this._metrics.length * 100;
-    this._metrics.forEach((m, i) => {
-      const x = legendX + i * 100;
-      const rect = document.createElementNS(svgNS, 'rect');
-      rect.setAttribute('x', x); rect.setAttribute('y', '4');
-      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
-      rect.setAttribute('rx', '2');
-      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
-      svg.appendChild(rect);
-
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = m.replace(/_/g, ' ');
-      svg.appendChild(text);
-    });
-  },
-
-  _renderSnapList(snaps) {
-    const el = document.getElementById('snapshot-list');
-    if (!el) return;
-    clearEl(el);
-    if (!snaps.length) {
-      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
-      return;
-    }
-    snaps.forEach((s, idx) => {
-      const healthPct = Number(s.health_score) || 0;
-      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
-      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
-
-      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
-      if (idx < snaps.length - 1) {
-        const prev = snaps[idx + 1];
-        const defs = [
-          { key: 'instruction_count', label: 'inst' },
-          { key: 'health_score', label: 'health' },
-          { key: 'unit_count', label: 'units' },
-        ];
-        defs.forEach(d => {
-          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
-          if (delta !== 0) {
-            const cls = delta > 0 ? 'positive' : 'negative';
-            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
-              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
-          }
-        });
-      }
-
-      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
-        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
-        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
-        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
-        deltas,
-        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
-        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
-          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
-      ));
-    });
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Insights View
-   ============================================================ */
-
-const insightEmptyReasons = {
-  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
-  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
-  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
-  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
-  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
-  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
-};
-
-const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
-
-const InsightsView = {
-  _running: new Set(),
-
-  async render() {
-    this._running = new Set();
-    const container = h('div', {});
-    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
-    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
-    container.appendChild(grid);
-    Shell.renderMain(container);
-
-    const snap = State.get('currentSnapshot');
-    if (!snap) {
-      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
-      return;
-    }
-
-    const res = await API.insights(snap.id);
-    const insights = Array.isArray(res.data) ? res.data : [];
-
-    if (!insights.length) {
-      grid.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, 'No insights available'),
-        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
-      return;
-    }
-
-    const available = insights.filter(i => i.available);
-    const unavailable = insights.filter(i => !i.available);
-
-    if (available.length) {
-      available.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
-      });
-    }
-
-    if (unavailable.length) {
-      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
-      unavailable.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
-      });
-    }
-
-    available.forEach((insight, idx) => {
-      this._runInsight(insight, idx, snap.id);
-    });
-  },
-
-  _renderInsightCard(insight, idx, snapId) {
-    const category = CapabilityData.category(insight.required_capability || '');
-    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
-      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
-      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
-      h('div', { class: 'insight-desc' }, insight.description || '')
-    );
-
-    if (!insight.available) {
-      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
-      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return card;
-    }
-
-    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
-    body.appendChild(h('div', { class: 'insight-skeleton' }));
-    card.appendChild(body);
-    return card;
-  },
-
-  async _runInsight(insight, idx, snapId) {
-    if (this._running.has(insight.name)) return;
-    this._running.add(insight.name);
-
-    const body = document.getElementById(`insight-body-${idx}`);
-    if (!body) return;
-
-    let res = null;
-    if (insightNeedsBaseline.has(insight.name)) {
-      const snaps = State.get('snapshots') || [];
-      const curIdx = snaps.findIndex(s => s.id === snapId);
-      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
-        res = await API.insight(snapId, insight.name, snaps[i].id);
-      }
-      if (!res?.ok) res = await API.insight(snapId, insight.name);
-    } else {
-      res = await API.insight(snapId, insight.name);
-    }
-    clearEl(body);
-
-    if (!res.ok) {
-      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
-      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return;
-    }
-
-    const rawData = res.data?.data || res.data;
-    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
-      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
-        h('div', {}, 'No data to display'),
-        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
-      return;
-    }
-
-    const rendered = this._renderInsightData(insight.name, rawData);
-    if (rendered) {
-      body.appendChild(rendered);
-    } else {
-      const normalized = CapabilityData.normalizeResults([
-        { capability: insight.required_capability || insight.name, value: rawData }
-      ])[0];
-      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
-    }
-  },
-
-  _renderInsightData(name, data) {
-    const d = data || {};
-    const wrap = h('div', { class: 'insight-content' });
-
-    if (name === 'pass_impact') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
-      const byType = d.by_type || {};
-      Object.entries(byType).forEach(([k, v]) => {
-        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
-      });
-      wrap.appendChild(metrics);
-      if (d.by_type && Object.keys(d.by_type).length > 1) {
-        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
-        const donut = UI.donutChart(donutData, { size: 100 });
-        if (donut) wrap.appendChild(donut);
-      }
-      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'function_complexity') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
-      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'debug_info') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
-      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
-      wrap.appendChild(metrics);
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    if (name === 'section_sizes') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
-      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
-      wrap.appendChild(metrics);
-      const cats = d.category_breakdown || {};
-      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
-      if (catEntries.length) {
-        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
-        const flame = UI.flameBars(flameItems);
-        if (flame) wrap.appendChild(flame);
-        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
-        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
-        catEntries.forEach(([label, v], i) => {
-          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
-            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
-            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
-      if (sections.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
-        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      return wrap;
-    }
-
-    if (name === 'loop_nesting') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'diagnostic_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
-      wrap.appendChild(metrics);
-      const base = d.baseline || {};
-      const prim = d.primary || {};
-      if (base.errors != null || prim.errors != null) {
-        const items = [
-          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
-          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
-          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
-        ];
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
-      if (newDiags.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
-        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'optimization_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
-      wrap.appendChild(metrics);
-      const byType = d.by_type_delta || {};
-      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
-      if (cleanEntries.length) {
-        const items = cleanEntries.map(([label, v]) => ({
-          label: titleCase(label),
-          before: v?.baseline || 0,
-          after: v?.primary || 0,
-        }));
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'header_depth') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
-      wrap.appendChild(metrics);
-      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
-      if (chains.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
-        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
-      }
-      const most = Array.isArray(d.most_included) ? d.most_included : [];
-      if (most.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
-        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
-      }
-      if (!chains.length && !most.length && !d.max_depth) {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'call_frequency') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
-      wrap.appendChild(metrics);
-      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
-      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
-      if (fanIn.length && fanInHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
-        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      if (fanOut.length && fanOutHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
-        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
-      if (hubs.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
-        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
-      }
-      if (!fanInHasData && !fanOutHasData && fanOut.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
-        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'compilation_flow') {
-      const stages = Array.isArray(d.stages) ? d.stages : [];
-      const total = d.total_duration_ms || 0;
-      const slowest = d.slowest_event || {};
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' },
-        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
-      if (slowest.name) {
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Event'),
-          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Time'),
-          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
-      }
-      wrap.appendChild(metrics);
-      if (stages.length) {
-        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
-        // Stacked horizontal bar
-        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
-        stages.forEach(s => {
-          const pct = s.pct_of_total || 0;
-          if (pct <= 0) return;
-          const color = colors[s.stage] || '#9B7DB8';
-          const seg = h('div', {
-            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
-                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
-            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
-          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
-          bar.appendChild(seg);
-        });
-        wrap.appendChild(bar);
-        // Legend rows
-        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
-        stages.forEach(s => {
-          const color = colors[s.stage] || '#9B7DB8';
-          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
-            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
-            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
-            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
-            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      return wrap;
-    }
-
-    if (name === 'metric_trends') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
-      wrap.appendChild(metrics);
-      if (d.functions > 0 && d.instructions > 0) {
-        const donutData = [
-          { label: 'Functions', value: d.functions },
-          { label: 'Globals', value: d.globals || 0 },
-        ].filter(x => x.value > 0);
-        if (donutData.length > 1) {
-          const donut = UI.donutChart(donutData, { size: 90 });
-          if (donut) wrap.appendChild(donut);
-        }
-      }
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    return null;
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Remarks Explorer View
-   ============================================================ */
-
 const RemarksView = {
   async render() {
     const snap = State.get('currentSnapshot');
@@ -5718,8 +4847,6 @@
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
-      Router.register('/timeline', () => TimelineView.render());
-      Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/explorer', () => CodeExplorerView.render());
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
index aecb3f9caa6ae..265cc9ba429df 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/compare.js
@@ -450,8 +450,7 @@ const CompareView = {
 
   async _loadUnitDetail(detail, change) {
     const matchType = change.match_type || 'changed';
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.debug.summary'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
 
     const unitId = change.candidate_unit_id || change.base_unit_id;
     const snapId = change.candidate_unit_id ? this._candidateId : this._baseId;
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index f85d22315b176..8d22e354161a4 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -8,8 +8,6 @@ const Icons = {
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
-  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
-  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
@@ -124,17 +122,10 @@ const API = {
     }
     return API.get(url);
   },
-  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
-  insight: (snapId, name, baseline) => {
-    let url = `/snapshots/${snapId}/insights/${name}`;
-    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
-    return API.get(url);
-  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
   compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
-  jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
     let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
     if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
@@ -254,7 +245,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
index 9e05cff690c06..6536ed1fd7b9d 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index.html
@@ -24,8 +24,6 @@
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
-      Router.register('/timeline', () => TimelineView.render());
-      Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/explorer', () => CodeExplorerView.render());
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 52cb1276a0ee6..9c804bf1b7b27 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -748,8 +748,6 @@ const Icons = {
   overview: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="6" height="6" rx="1"/><rect x="11" y="3" width="6" height="6" rx="1"/><rect x="3" y="11" width="6" height="6" rx="1"/><rect x="11" y="11" width="6" height="6" rx="1"/></svg>`,
   units: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/></svg>`,
   compare: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polyline points="3,14 7,6 11,12 15,4 17,8"/></svg>`,
-  timeline: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="7"/><polyline points="10,6 10,10 13,12"/></svg>`,
-  insights: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="10,2 12,8 18,8 13,12 15,18 10,14 5,18 7,12 2,8 8,8"/></svg>`,
   remarks: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="14" height="10" rx="1.5"/><line x1="6" y1="7" x2="14" y2="7"/><line x1="6" y1="9.5" x2="11" y2="9.5"/><polyline points="7,13 5,17 10,15 15,17 13,13"/></svg>`,
   heatmap: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="7" rx="1" fill="rgba(255,100,100,0.3)"/><rect x="11" y="2" width="7" height="7" rx="1" fill="rgba(255,150,50,0.3)"/><rect x="2" y="11" width="7" height="7" rx="1" fill="rgba(255,200,50,0.3)"/><rect x="11" y="11" width="7" height="7" rx="1" fill="rgba(100,200,100,0.3)"/></svg>`,
   settings: `<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="3"/><path d="M10,2v3M10,15v3M2,10h3M15,10h3M4.2,4.2l2.1,2.1M13.7,13.7l2.1,2.1M4.2,15.8l2.1-2.1M13.7,6.3l2.1-2.1"/></svg>`,
@@ -864,17 +862,10 @@ const API = {
     }
     return API.get(url);
   },
-  insights: (snapId) => API.get(`/snapshots/${snapId}/insights`),
-  insight: (snapId, name, baseline) => {
-    let url = `/snapshots/${snapId}/insights/${name}`;
-    if (baseline) url += `?baseline=${encodeURIComponent(baseline)}`;
-    return API.get(url);
-  },
   compare: (before, after) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}`),
   compareRemarks: (before, after, offset, limit) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks?offset=${offset||0}&limit=${limit||100}`),
   compareFunctionDetail: (before, after, fn) => API.get(`/compare/${encodeURIComponent(before)}/${encodeURIComponent(after)}/remarks/${encodeURIComponent(fn)}`),
   inspect: (mode, body) => API.post(`/inspect/${encodeURIComponent(mode)}`, body),
-  jobs: () => API.get('/jobs'),
   async importFile(file, sourceRoot) {
     let url = `${this.base}/import?filename=${encodeURIComponent(file.name)}`;
     if (sourceRoot) url += `&source_root=${encodeURIComponent(sourceRoot)}`;
@@ -994,7 +985,7 @@ const Keys = {
     if (this._pending === 'g') {
       clearTimeout(this._timeout);
       this._pending = null;
-      const navMap = { o: '/', u: '/units', c: '/compare', t: '/timeline', i: '/insights', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
+      const navMap = { o: '/', u: '/units', c: '/compare', r: '/remarks', h: '/heatmap', e: '/explorer', s: '/settings' };
       if (navMap[e.key]) { e.preventDefault(); Router.navigate(navMap[e.key]); }
       return;
     }
@@ -2202,8 +2193,6 @@ const Shell = {
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
-      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
-      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
@@ -2331,8 +2320,6 @@ const CommandPalette = {
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
-    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
-    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
@@ -2455,10 +2442,7 @@ const OverviewView = {
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary',
-                      'llvm.debug.summary', 'clang.ast.summary',
-                      'llvm.lto.summary', 'llvm.lto.function_stats'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
@@ -3260,7 +3244,7 @@ const UnitDetailView = {
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
+    const tabs = ['Overview', 'Remarks', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -3304,76 +3288,6 @@ const UnitDetailView = {
     );
   },
 
-  openFunctionExplorer(unit, snapshotId, functionName) {
-    const container = document.getElementById('inline-explorer');
-    if (!container) return;
-    clearEl(container);
-
-    const card = h('div', { class: 'inline-explorer' });
-    const header = h('div', { class: 'inline-explorer-header' },
-      h('span', { class: 'capability-card-title mono' }, functionName),
-      h('button', {
-        class: 'detail-card-close',
-        onClick: () => clearEl(container),
-        title: 'Close'
-      }, '×')
-    );
-
-    const controls = h('div', { class: 'cap-pills' });
-    const body = h('div', { class: 'capability-stack' });
-    const modes = [
-      ['signals', 'Signals'],
-      ['ir', 'IR'],
-      ['cfg', 'CFG'],
-      ['dom', 'Dom'],
-      ['loop', 'Loops'],
-      ['callgraph', 'Call Graph'],
-      ['asm', 'Asm'],
-      ['mca', 'MCA'],
-      ['remarks', 'Remarks'],
-      ['debug', 'Debug'],
-      ['passes', 'Passes'],
-    ];
-
-    const loadMode = async (mode, pill) => {
-      Array.from(controls.children).forEach(node => node.classList.remove('available'));
-      if (pill) pill.classList.add('available');
-      clearEl(body);
-      body.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, `Loading ${mode}`),
-        h('div', { class: 'reason mono' }, functionName)));
-      const res = await API.inspect(mode, {
-        snapshot_id: snapshotId,
-        unit: unit.id,
-        function: functionName,
-      });
-      clearEl(body);
-      if (!res.ok) {
-        body.appendChild(h('div', { class: 'empty-state' },
-          h('div', {}, 'Inspection failed'),
-          h('div', { class: 'reason mono' }, res.error || 'unknown error')));
-        return;
-      }
-      body.appendChild(UI.inspectResult(res.data));
-    };
-
-    modes.forEach(([mode, label], index) => {
-      const pill = h('button', {
-        class: `cap-pill ${index === 0 ? 'available' : ''}`,
-        onClick: () => loadMode(mode, pill),
-      }, label);
-      controls.appendChild(pill);
-      if (index === 0) setTimeout(() => loadMode(mode, pill), 0);
-    });
-
-    card.appendChild(header);
-    card.appendChild(controls);
-    card.appendChild(body);
-    container.appendChild(card);
-
-    // Scroll into view
-    card.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
-  },
 
   renderCapSidebar(sidebar, unit) {
     clearEl(sidebar);
@@ -3387,29 +3301,6 @@ const UnitDetailView = {
       h('div', { class: 'rail-title' }, 'Coverage'),
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
-    // Function list placeholder in sidebar
-    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
-      h('div', { class: 'rail-title' }, 'Functions'),
-      h('div', { class: 'rail-empty' }, 'Loading function list')
-    ));
-  },
-
-  addSection(parent, title, open, kvPairs) {
-    const section = h('div', { class: 'cap-section' + (open ? ' open' : '') });
-    const header = h('div', { class: 'cap-section-header', onClick: () => section.classList.toggle('open') },
-      h('span', {}, title)
-    );
-    const body = h('div', { class: 'cap-section-body' });
-    kvPairs.forEach(([k, v]) => {
-      body.appendChild(h('div', { class: 'kv' },
-        h('span', { class: 'k' }, k),
-        h('span', { class: 'v' }, v)
-      ));
-    });
-    section.appendChild(header);
-    section.appendChild(body);
-    parent.appendChild(section);
-  },
 
   renderTab(tab, state) {
     if (!state.results.length)
@@ -3417,20 +3308,6 @@ const UnitDetailView = {
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
-    if (tab === 'Diagnostics') {
-      const findings = state.results
-        .filter(r => r.capability.startsWith('clang.diag'))
-        .flatMap(r => r.findings);
-      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
-      const bySev = {};
-      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
-      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
-      return h('div', { class: 'capability-stack' },
-        chartData.length ? UI.barChart(chartData) : null,
-        UI.findingList(findings)
-      );
-    }
-
     if (tab === 'Remarks') {
       const relResult = state.byCapability.get('llvm.remarks.relational');
       if (relResult && relResult.available && relResult.value && relResult.value.columns) {
@@ -3453,13 +3330,6 @@ const UnitDetailView = {
       );
     }
 
-    if (tab === 'Functions') {
-      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
-      const rows = fnResult?.value?.functions || [];
-      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
-      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
-    }
-
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -3477,9 +3347,6 @@ const UnitDetailView = {
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
-        this.summaryCard('Functions', metrics.functions, 'neutral'),
-        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
-        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -3503,12 +3370,9 @@ const UnitDetailView = {
   },
 
   collectOverview(results) {
-    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
+    const metrics = { remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
-      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
-      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
-      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -3518,7 +3382,7 @@ const UnitDetailView = {
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
+      : ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -3530,30 +3394,6 @@ const UnitDetailView = {
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
-    // Populate function list in sidebar
-    const fnCard = sidebar.querySelector('#function-list-card');
-    results.forEach(r => {
-      const val = r.value;
-      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
-        if (fnCard) {
-          clearEl(fnCard);
-          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
-          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
-          const list = h('div', { class: 'fn-section' });
-          fns.slice(0, 50).forEach(fn => {
-            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
-              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
-              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
-            ));
-          });
-          if (fns.length > 50) {
-            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
-              `+ ${fns.length - 50} more…`));
-          }
-          fnCard.appendChild(list);
-        }
-      }
-    });
     if (refresh) refresh();
   },
 
@@ -4030,8 +3870,7 @@ const CompareView = {
 
   async _loadUnitDetail(detail, change) {
     const matchType = change.match_type || 'changed';
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.debug.summary'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail'];
 
     const unitId = change.candidate_unit_id || change.base_unit_id;
     const snapId = change.candidate_unit_id ? this._candidateId : this._baseId;
@@ -4076,716 +3915,6 @@ const CompareView = {
 
   </script>
   <script>
-/* ============================================================
-   LLVM Advisor — Timeline View
-   ============================================================ */
-
-const TimelineView = {
-  _metrics: ['unit_count', 'instruction_count', 'health_score'],
-  _colors: {
-    unit_count: '#5B8DB8',
-    instruction_count: '#5DB8A8',
-    health_score: '#6EC9C4',
-    warning_count: '#D4A574',
-    error_count: '#D48B9B',
-  },
-  _snapData: [],
-
-  async render() {
-    const container = h('div', {});
-
-    const chips = h('div', { class: 'metric-chips' });
-    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
-      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
-      const chip = h('div', {
-        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
-        onClick: () => {
-          const idx = this._metrics.indexOf(m);
-          if (idx >= 0) this._metrics.splice(idx, 1);
-          else if (this._metrics.length < 4) this._metrics.push(m);
-          chip.classList.toggle('active');
-          this._drawChart();
-        },
-      },
-        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
-        label
-      );
-      chips.appendChild(chip);
-    });
-    container.appendChild(chips);
-
-    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
-
-    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
-
-    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
-    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
-
-    Shell.renderMain(container);
-    await this._loadData();
-  },
-
-  async _loadData() {
-    const snaps = State.get('snapshots') || [];
-    if (!snaps.length) {
-      this._renderSnapList([]);
-      return;
-    }
-
-    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
-    this._snapData = snaps.map((s, i) => {
-      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
-      return {
-        ...s,
-        unit_count: sum.unit_count ?? s.unit_count ?? 0,
-        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
-        health_score: sum.health_score ?? 0,
-        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
-        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
-        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
-        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
-      };
-    });
-
-    this._renderSnapList(this._snapData);
-    this._renderMetricCards();
-    this._drawChart();
-  },
-
-  _renderMetricCards() {
-    const el = document.getElementById('timeline-metrics');
-    if (!el || !this._snapData.length) return;
-    clearEl(el);
-    const latest = this._snapData[0];
-    const metricDefs = [
-      { key: 'unit_count', label: 'Units' },
-      { key: 'instruction_count', label: 'Instructions' },
-      { key: 'health_score', label: 'Health' },
-      { key: 'remark_count', label: 'Remarks' },
-      { key: 'function_count', label: 'Functions' },
-    ];
-    metricDefs.forEach(m => {
-      const val = latest[m.key] ?? 0;
-      let delta = null, deltaCls = 'neutral';
-      if (this._snapData.length > 1) {
-        const prev = this._snapData[1];
-        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
-        if (d !== 0) {
-          const sign = d > 0 ? '+' : '';
-          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
-          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
-          delta = `${sign}${formatNumber(d)} vs prev`;
-        }
-      }
-      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
-    });
-  },
-
-  _drawChart() {
-    const container = document.getElementById('timeline-chart-container');
-    if (!container) return;
-    clearEl(container);
-    const data = this._snapData;
-    const svgNS = 'http://www.w3.org/2000/svg';
-    const svg = document.createElementNS(svgNS, 'svg');
-    svg.style.width = '100%';
-    svg.style.height = '220px';
-    container.appendChild(svg);
-
-    if (data.length < 2) {
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
-      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
-      svg.appendChild(text);
-      return;
-    }
-
-    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
-    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
-    const chartW = w - padL - padR;
-    const chartH = ht - padT - padB;
-
-    // Horizontal grid lines
-    for (let i = 0; i <= 4; i++) {
-      const y = padT + (chartH * i / 4);
-      const line = document.createElementNS(svgNS, 'line');
-      line.setAttribute('x1', padL); line.setAttribute('y1', y);
-      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
-      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
-      line.setAttribute('stroke-width', '1');
-      svg.appendChild(line);
-    }
-
-    const xStep = chartW / (data.length - 1);
-
-    this._metrics.forEach(m => {
-      const values = data.map(s => Number(s[m]) || 0);
-      const max = Math.max(...values, 1);
-      const min = Math.min(...values, 0);
-      const range = max - min || 1;
-      const color = this._colors[m] || 'var(--accent)';
-
-      const points = data.map((_, i) => {
-        const x = padL + i * xStep;
-        const y = padT + chartH - ((values[i] - min) / range) * chartH;
-        return `${x.toFixed(1)},${y.toFixed(1)}`;
-      });
-
-      // Area fill
-      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
-      const area = document.createElementNS(svgNS, 'polygon');
-      area.setAttribute('points', areaPoints);
-      area.setAttribute('fill', color);
-      area.setAttribute('opacity', '0.08');
-      svg.appendChild(area);
-
-      const poly = document.createElementNS(svgNS, 'polyline');
-      poly.setAttribute('points', points.join(' '));
-      poly.setAttribute('fill', 'none');
-      poly.setAttribute('stroke', color);
-      poly.setAttribute('stroke-width', '2');
-      poly.setAttribute('stroke-linejoin', 'round');
-      svg.appendChild(poly);
-
-      data.forEach((_, i) => {
-        const [x, y] = points[i].split(',');
-        const circle = document.createElementNS(svgNS, 'circle');
-        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
-        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
-        svg.appendChild(circle);
-      });
-
-      // Y-axis labels for first metric only
-      if (m === this._metrics[0]) {
-        for (let i = 0; i <= 4; i++) {
-          const val = min + (range * (4 - i) / 4);
-          const y = padT + (chartH * i / 4);
-          const text = document.createElementNS(svgNS, 'text');
-          text.setAttribute('x', String(padL - 6));
-          text.setAttribute('y', String(y + 3));
-          text.setAttribute('text-anchor', 'end');
-          text.setAttribute('fill', 'var(--fg3)');
-          text.setAttribute('font-size', '9');
-          text.setAttribute('font-family', 'var(--mono)');
-          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
-          svg.appendChild(text);
-        }
-      }
-    });
-
-    // X-axis labels
-    data.forEach((s, i) => {
-      const x = padL + i * xStep;
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = (s.id || '').slice(0, 6);
-      svg.appendChild(text);
-    });
-
-    // Legend
-    const legendX = w - padR - this._metrics.length * 100;
-    this._metrics.forEach((m, i) => {
-      const x = legendX + i * 100;
-      const rect = document.createElementNS(svgNS, 'rect');
-      rect.setAttribute('x', x); rect.setAttribute('y', '4');
-      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
-      rect.setAttribute('rx', '2');
-      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
-      svg.appendChild(rect);
-
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = m.replace(/_/g, ' ');
-      svg.appendChild(text);
-    });
-  },
-
-  _renderSnapList(snaps) {
-    const el = document.getElementById('snapshot-list');
-    if (!el) return;
-    clearEl(el);
-    if (!snaps.length) {
-      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
-      return;
-    }
-    snaps.forEach((s, idx) => {
-      const healthPct = Number(s.health_score) || 0;
-      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
-      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
-
-      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
-      if (idx < snaps.length - 1) {
-        const prev = snaps[idx + 1];
-        const defs = [
-          { key: 'instruction_count', label: 'inst' },
-          { key: 'health_score', label: 'health' },
-          { key: 'unit_count', label: 'units' },
-        ];
-        defs.forEach(d => {
-          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
-          if (delta !== 0) {
-            const cls = delta > 0 ? 'positive' : 'negative';
-            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
-              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
-          }
-        });
-      }
-
-      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
-        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
-        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
-        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
-        deltas,
-        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
-        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
-          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
-      ));
-    });
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Insights View
-   ============================================================ */
-
-const insightEmptyReasons = {
-  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
-  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
-  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
-  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
-  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
-  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
-};
-
-const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
-
-const InsightsView = {
-  _running: new Set(),
-
-  async render() {
-    this._running = new Set();
-    const container = h('div', {});
-    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
-    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
-    container.appendChild(grid);
-    Shell.renderMain(container);
-
-    const snap = State.get('currentSnapshot');
-    if (!snap) {
-      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
-      return;
-    }
-
-    const res = await API.insights(snap.id);
-    const insights = Array.isArray(res.data) ? res.data : [];
-
-    if (!insights.length) {
-      grid.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, 'No insights available'),
-        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
-      return;
-    }
-
-    const available = insights.filter(i => i.available);
-    const unavailable = insights.filter(i => !i.available);
-
-    if (available.length) {
-      available.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
-      });
-    }
-
-    if (unavailable.length) {
-      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
-      unavailable.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
-      });
-    }
-
-    available.forEach((insight, idx) => {
-      this._runInsight(insight, idx, snap.id);
-    });
-  },
-
-  _renderInsightCard(insight, idx, snapId) {
-    const category = CapabilityData.category(insight.required_capability || '');
-    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
-      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
-      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
-      h('div', { class: 'insight-desc' }, insight.description || '')
-    );
-
-    if (!insight.available) {
-      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
-      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return card;
-    }
-
-    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
-    body.appendChild(h('div', { class: 'insight-skeleton' }));
-    card.appendChild(body);
-    return card;
-  },
-
-  async _runInsight(insight, idx, snapId) {
-    if (this._running.has(insight.name)) return;
-    this._running.add(insight.name);
-
-    const body = document.getElementById(`insight-body-${idx}`);
-    if (!body) return;
-
-    let res = null;
-    if (insightNeedsBaseline.has(insight.name)) {
-      const snaps = State.get('snapshots') || [];
-      const curIdx = snaps.findIndex(s => s.id === snapId);
-      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
-        res = await API.insight(snapId, insight.name, snaps[i].id);
-      }
-      if (!res?.ok) res = await API.insight(snapId, insight.name);
-    } else {
-      res = await API.insight(snapId, insight.name);
-    }
-    clearEl(body);
-
-    if (!res.ok) {
-      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
-      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return;
-    }
-
-    const rawData = res.data?.data || res.data;
-    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
-      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
-        h('div', {}, 'No data to display'),
-        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
-      return;
-    }
-
-    const rendered = this._renderInsightData(insight.name, rawData);
-    if (rendered) {
-      body.appendChild(rendered);
-    } else {
-      const normalized = CapabilityData.normalizeResults([
-        { capability: insight.required_capability || insight.name, value: rawData }
-      ])[0];
-      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
-    }
-  },
-
-  _renderInsightData(name, data) {
-    const d = data || {};
-    const wrap = h('div', { class: 'insight-content' });
-
-    if (name === 'pass_impact') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
-      const byType = d.by_type || {};
-      Object.entries(byType).forEach(([k, v]) => {
-        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
-      });
-      wrap.appendChild(metrics);
-      if (d.by_type && Object.keys(d.by_type).length > 1) {
-        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
-        const donut = UI.donutChart(donutData, { size: 100 });
-        if (donut) wrap.appendChild(donut);
-      }
-      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'function_complexity') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
-      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'debug_info') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
-      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
-      wrap.appendChild(metrics);
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    if (name === 'section_sizes') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
-      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
-      wrap.appendChild(metrics);
-      const cats = d.category_breakdown || {};
-      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
-      if (catEntries.length) {
-        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
-        const flame = UI.flameBars(flameItems);
-        if (flame) wrap.appendChild(flame);
-        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
-        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
-        catEntries.forEach(([label, v], i) => {
-          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
-            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
-            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
-      if (sections.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
-        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      return wrap;
-    }
-
-    if (name === 'loop_nesting') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'diagnostic_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
-      wrap.appendChild(metrics);
-      const base = d.baseline || {};
-      const prim = d.primary || {};
-      if (base.errors != null || prim.errors != null) {
-        const items = [
-          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
-          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
-          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
-        ];
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
-      if (newDiags.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
-        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'optimization_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
-      wrap.appendChild(metrics);
-      const byType = d.by_type_delta || {};
-      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
-      if (cleanEntries.length) {
-        const items = cleanEntries.map(([label, v]) => ({
-          label: titleCase(label),
-          before: v?.baseline || 0,
-          after: v?.primary || 0,
-        }));
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'header_depth') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
-      wrap.appendChild(metrics);
-      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
-      if (chains.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
-        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
-      }
-      const most = Array.isArray(d.most_included) ? d.most_included : [];
-      if (most.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
-        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
-      }
-      if (!chains.length && !most.length && !d.max_depth) {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'call_frequency') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
-      wrap.appendChild(metrics);
-      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
-      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
-      if (fanIn.length && fanInHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
-        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      if (fanOut.length && fanOutHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
-        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
-      if (hubs.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
-        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
-      }
-      if (!fanInHasData && !fanOutHasData && fanOut.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
-        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'compilation_flow') {
-      const stages = Array.isArray(d.stages) ? d.stages : [];
-      const total = d.total_duration_ms || 0;
-      const slowest = d.slowest_event || {};
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' },
-        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
-      if (slowest.name) {
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Event'),
-          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Time'),
-          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
-      }
-      wrap.appendChild(metrics);
-      if (stages.length) {
-        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
-        // Stacked horizontal bar
-        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
-        stages.forEach(s => {
-          const pct = s.pct_of_total || 0;
-          if (pct <= 0) return;
-          const color = colors[s.stage] || '#9B7DB8';
-          const seg = h('div', {
-            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
-                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
-            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
-          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
-          bar.appendChild(seg);
-        });
-        wrap.appendChild(bar);
-        // Legend rows
-        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
-        stages.forEach(s => {
-          const color = colors[s.stage] || '#9B7DB8';
-          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
-            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
-            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
-            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
-            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      return wrap;
-    }
-
-    if (name === 'metric_trends') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
-      wrap.appendChild(metrics);
-      if (d.functions > 0 && d.instructions > 0) {
-        const donutData = [
-          { label: 'Functions', value: d.functions },
-          { label: 'Globals', value: d.globals || 0 },
-        ].filter(x => x.value > 0);
-        if (donutData.length > 1) {
-          const donut = UI.donutChart(donutData, { size: 90 });
-          if (donut) wrap.appendChild(donut);
-        }
-      }
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    return null;
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Remarks Explorer View
-   ============================================================ */
-
 const RemarksView = {
   async render() {
     const snap = State.get('currentSnapshot');
@@ -5721,8 +4850,6 @@ const CodeExplorerView = {
       Router.register('/units', () => UnitsView.render());
       Router.register('/units/:id', params => UnitDetailView.render(params));
       Router.register('/compare', params => CompareView.render(params));
-      Router.register('/timeline', () => TimelineView.render());
-      Router.register('/insights', () => InsightsView.render());
       Router.register('/remarks', () => RemarksView.render());
       Router.register('/heatmap', () => HeatmapView.render());
       Router.register('/explorer', () => CodeExplorerView.render());
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
index ba7c08107599e..2ccacfb8ccce7 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/overview.js
@@ -72,10 +72,7 @@ const OverviewView = {
     }
 
     // Query core capabilities only — avoid expensive/unstable capabilities
-    const coreCaps = ['llvm.ir.summary', 'llvm.ir.function_stats', 'clang.diag.summary',
-                      'llvm.obj.summary', 'llvm.remarks.summary',
-                      'llvm.debug.summary', 'clang.ast.summary',
-                      'llvm.lto.summary', 'llvm.lto.function_stats'];
+    const coreCaps = ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const registeredIds = new Set(specs.map(s => s.id));
     const dashboardCaps = coreCaps.filter(id => registeredIds.size === 0 || registeredIds.has(id));
     let aggregate = { metrics: {}, rows: [], errors: 0, warnings: 0, remarks: 0, unavailable: 0, families: [] };
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
index 8718fdc868701..3a46a97ea32e3 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/shell.js
@@ -161,8 +161,6 @@ const Shell = {
       { icon: 'overview', label: 'Overview', route: '/', shortcut: 'g o' },
       { icon: 'units', label: 'Units', route: '/units', shortcut: 'g u' },
       { icon: 'compare', label: 'Compare', route: '/compare', shortcut: 'g c' },
-      { icon: 'timeline', label: 'Timeline', route: '/timeline', shortcut: 'g t' },
-      { icon: 'insights', label: 'Insights', route: '/insights', shortcut: 'g i' },
       { icon: 'remarks', label: 'Remarks', route: '/remarks', shortcut: 'g r' },
       { icon: 'heatmap', label: 'Heatmap', route: '/heatmap', shortcut: 'g h' },
       { icon: 'explorer', label: 'Explorer', route: '/explorer', shortcut: 'g e' },
@@ -290,8 +288,6 @@ const CommandPalette = {
     { label: 'Go to Overview', shortcut: 'g o', action: () => Router.navigate('/') },
     { label: 'Go to Units', shortcut: 'g u', action: () => Router.navigate('/units') },
     { label: 'Go to Compare', shortcut: 'g c', action: () => Router.navigate('/compare') },
-    { label: 'Go to Timeline', shortcut: 'g t', action: () => Router.navigate('/timeline') },
-    { label: 'Go to Insights', shortcut: 'g i', action: () => Router.navigate('/insights') },
     { label: 'Go to Remarks', shortcut: 'g r', action: () => Router.navigate('/remarks') },
     { label: 'Go to Heatmap', shortcut: 'g h', action: () => Router.navigate('/heatmap') },
     { label: 'Go to Explorer', shortcut: 'g e', action: () => Router.navigate('/explorer') },
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
index 64c4b5cc766ee..99e2ca8c285b0 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/unit-detail.js
@@ -55,7 +55,7 @@ const UnitDetailView = {
     const tabState = { active: 'Overview', results: [], byCapability: new Map() };
 
     // Code viewer and tabs
-    const tabs = ['Overview', 'Diagnostics', 'Remarks', 'Functions', 'Artifacts'];
+    const tabs = ['Overview', 'Remarks', 'Artifacts'];
     const tabHeaders = h('div', { class: 'code-tabs' });
     const contentArea = h('div', { class: 'code-content', id: 'code-content' });
     const inlineExplorer = h('div', { id: 'inline-explorer' });
@@ -99,76 +99,6 @@ const UnitDetailView = {
     );
   },
 
-  openFunctionExplorer(unit, snapshotId, functionName) {
-    const container = document.getElementById('inline-explorer');
-    if (!container) return;
-    clearEl(container);
-
-    const card = h('div', { class: 'inline-explorer' });
-    const header = h('div', { class: 'inline-explorer-header' },
-      h('span', { class: 'capability-card-title mono' }, functionName),
-      h('button', {
-        class: 'detail-card-close',
-        onClick: () => clearEl(container),
-        title: 'Close'
-      }, '×')
-    );
-
-    const controls = h('div', { class: 'cap-pills' });
-    const body = h('div', { class: 'capability-stack' });
-    const modes = [
-      ['signals', 'Signals'],
-      ['ir', 'IR'],
-      ['cfg', 'CFG'],
-      ['dom', 'Dom'],
-      ['loop', 'Loops'],
-      ['callgraph', 'Call Graph'],
-      ['asm', 'Asm'],
-      ['mca', 'MCA'],
-      ['remarks', 'Remarks'],
-      ['debug', 'Debug'],
-      ['passes', 'Passes'],
-    ];
-
-    const loadMode = async (mode, pill) => {
-      Array.from(controls.children).forEach(node => node.classList.remove('available'));
-      if (pill) pill.classList.add('available');
-      clearEl(body);
-      body.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, `Loading ${mode}`),
-        h('div', { class: 'reason mono' }, functionName)));
-      const res = await API.inspect(mode, {
-        snapshot_id: snapshotId,
-        unit: unit.id,
-        function: functionName,
-      });
-      clearEl(body);
-      if (!res.ok) {
-        body.appendChild(h('div', { class: 'empty-state' },
-          h('div', {}, 'Inspection failed'),
-          h('div', { class: 'reason mono' }, res.error || 'unknown error')));
-        return;
-      }
-      body.appendChild(UI.inspectResult(res.data));
-    };
-
-    modes.forEach(([mode, label], index) => {
-      const pill = h('button', {
-        class: `cap-pill ${index === 0 ? 'available' : ''}`,
-        onClick: () => loadMode(mode, pill),
-      }, label);
-      controls.appendChild(pill);
-      if (index === 0) setTimeout(() => loadMode(mode, pill), 0);
-    });
-
-    card.appendChild(header);
-    card.appendChild(controls);
-    card.appendChild(body);
-    container.appendChild(card);
-
-    // Scroll into view
-    card.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
-  },
 
   renderCapSidebar(sidebar, unit) {
     clearEl(sidebar);
@@ -182,29 +112,6 @@ const UnitDetailView = {
       h('div', { class: 'rail-title' }, 'Coverage'),
       h('div', { class: 'rail-empty' }, 'Loading analysis coverage')
     ));
-    // Function list placeholder in sidebar
-    sidebar.appendChild(h('div', { class: 'unit-side-card', id: 'function-list-card' },
-      h('div', { class: 'rail-title' }, 'Functions'),
-      h('div', { class: 'rail-empty' }, 'Loading function list')
-    ));
-  },
-
-  addSection(parent, title, open, kvPairs) {
-    const section = h('div', { class: 'cap-section' + (open ? ' open' : '') });
-    const header = h('div', { class: 'cap-section-header', onClick: () => section.classList.toggle('open') },
-      h('span', {}, title)
-    );
-    const body = h('div', { class: 'cap-section-body' });
-    kvPairs.forEach(([k, v]) => {
-      body.appendChild(h('div', { class: 'kv' },
-        h('span', { class: 'k' }, k),
-        h('span', { class: 'v' }, v)
-      ));
-    });
-    section.appendChild(header);
-    section.appendChild(body);
-    parent.appendChild(section);
-  },
 
   renderTab(tab, state) {
     if (!state.results.length)
@@ -212,20 +119,6 @@ const UnitDetailView = {
         h('div', {}, 'Loading capabilities'),
         h('div', { class: 'reason mono' }, 'Querying analyzer results for this unit'));
 
-    if (tab === 'Diagnostics') {
-      const findings = state.results
-        .filter(r => r.capability.startsWith('clang.diag'))
-        .flatMap(r => r.findings);
-      if (!findings.length) return this.emptyTab('No diagnostics', 'This unit has no compiler diagnostics in the current snapshot.');
-      const bySev = {};
-      findings.forEach(f => { const s = (f.severity || 'info').toLowerCase(); bySev[s] = (bySev[s] || 0) + 1; });
-      const chartData = Object.entries(bySev).map(([label, amount]) => ({ label, amount }));
-      return h('div', { class: 'capability-stack' },
-        chartData.length ? UI.barChart(chartData) : null,
-        UI.findingList(findings)
-      );
-    }
-
     if (tab === 'Remarks') {
       const relResult = state.byCapability.get('llvm.remarks.relational');
       if (relResult && relResult.available && relResult.value && relResult.value.columns) {
@@ -248,13 +141,6 @@ const UnitDetailView = {
       );
     }
 
-    if (tab === 'Functions') {
-      const fnResult = state.byCapability.get('llvm.ir.function_stats') || state.byCapability.get('llvm.lto.function_stats');
-      const rows = fnResult?.value?.functions || [];
-      if (!rows.length) return this.emptyTab('No function stats', 'Function-level metrics are not available for this unit.');
-      return UI.dataTable(rows, { columns: ['name', 'instructions', 'basic_blocks', 'arg_count', 'stable_key'], limit: 500 });
-    }
-
     if (tab === 'Artifacts') {
       const artifacts = state.results.flatMap(r => r.artifacts.map(a => ({ capability: r.capability, ...a })));
       if (!artifacts.length)
@@ -272,9 +158,6 @@ const UnitDetailView = {
     return h('div', { class: 'unit-overview-panel' },
       h('div', { class: 'quiet-section-title' }, 'Summary'),
       h('div', { class: 'unit-overview-cards' },
-        this.summaryCard('Functions', metrics.functions, 'neutral'),
-        this.summaryCard('Basic blocks', metrics.basic_blocks, 'neutral'),
-        this.summaryCard('Sections', metrics.sections, 'neutral'),
         this.summaryCard('Remarks', metrics.remarks, metrics.remarks ? 'info' : 'neutral')
       ),
       h('div', { class: 'quiet-section-title' }, 'Available Analysis'),
@@ -298,12 +181,9 @@ const UnitDetailView = {
   },
 
   collectOverview(results) {
-    const metrics = { functions: 0, basic_blocks: 0, sections: 0, remarks: 0 };
+    const metrics = { remarks: 0 };
     results.forEach(r => {
       if (!r.available) return;
-      metrics.functions += Number(r.metrics.functions || r.metrics.function_count || 0);
-      metrics.basic_blocks += Number(r.metrics.basic_blocks || 0);
-      metrics.sections += Number(r.metrics.sections || 0);
       metrics.remarks += Number(r.metrics.count && r.capability.includes('remarks') ? r.metrics.count : 0);
     });
     return metrics;
@@ -313,7 +193,7 @@ const UnitDetailView = {
     const capRes = await API.capabilities();
     const caps = Array.isArray(capRes.data)
       ? capRes.data.filter(spec => CapabilityData.shouldQueryCapability(spec, 'unit')).map(c => c.id).filter(Boolean)
-      : ['clang.diag.summary', 'llvm.ir.function_stats', 'llvm.obj.summary', 'llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational'];
+      : ['llvm.remarks.summary', 'llvm.remarks.detail', 'llvm.remarks.relational', 'llvm.remarks.hotspot'];
     const res = await API.queryUnit(unit.id, caps);
     if (!res.ok) {
       if (main) main.appendChild(UI.errorCard(res.error || 'query failed', () => this.render({ id: unit.id, snapshot: unit.snapshot_id || State.get('currentSnapshot')?.id })));
@@ -325,30 +205,6 @@ const UnitDetailView = {
     tabState.byCapability = new Map(results.map(r => [r.capability, r]));
     this.renderCoverage(sidebar, results);
 
-    // Populate function list in sidebar
-    const fnCard = sidebar.querySelector('#function-list-card');
-    results.forEach(r => {
-      const val = r.value;
-      if ((r.capability === 'llvm.ir.function_stats' || r.capability === 'llvm.lto.function_stats') && val.functions) {
-        if (fnCard) {
-          clearEl(fnCard);
-          fnCard.appendChild(h('div', { class: 'rail-title' }, `Functions (${val.functions.length})`));
-          const fns = [...val.functions].sort((a, b) => (b.instructions || b.instruction_count || 0) - (a.instructions || a.instruction_count || 0));
-          const list = h('div', { class: 'fn-section' });
-          fns.slice(0, 50).forEach(fn => {
-            list.appendChild(h('button', { class: 'fn-list-item', onClick: () => this.openFunctionExplorer(unit, unit.snapshot_id || State.get('currentSnapshot')?.id, fn.name || '(anonymous)') },
-              h('span', { class: 'fn-name' }, fn.name || '(anonymous)'),
-              h('span', { class: 'fn-count' }, formatNumber(fn.instructions || fn.instruction_count))
-            ));
-          });
-          if (fns.length > 50) {
-            list.appendChild(h('div', { class: 'text-muted', style: { fontSize: '11px', padding: '4px 12px' } },
-              `+ ${fns.length - 50} more…`));
-          }
-          fnCard.appendChild(list);
-        }
-      }
-    });
     if (refresh) refresh();
   },
 
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
index 9bdf9bd2671da..fa8d899d68655 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/views.js
@@ -1,713 +1,3 @@
-/* ============================================================
-   LLVM Advisor — Timeline View
-   ============================================================ */
-
-const TimelineView = {
-  _metrics: ['unit_count', 'instruction_count', 'health_score'],
-  _colors: {
-    unit_count: '#5B8DB8',
-    instruction_count: '#5DB8A8',
-    health_score: '#6EC9C4',
-    warning_count: '#D4A574',
-    error_count: '#D48B9B',
-  },
-  _snapData: [],
-
-  async render() {
-    const container = h('div', {});
-
-    const chips = h('div', { class: 'metric-chips' });
-    ['unit_count', 'instruction_count', 'health_score', 'warning_count', 'error_count'].forEach(m => {
-      const label = m.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
-      const chip = h('div', {
-        class: 'metric-chip' + (this._metrics.includes(m) ? ' active' : ''),
-        onClick: () => {
-          const idx = this._metrics.indexOf(m);
-          if (idx >= 0) this._metrics.splice(idx, 1);
-          else if (this._metrics.length < 4) this._metrics.push(m);
-          chip.classList.toggle('active');
-          this._drawChart();
-        },
-      },
-        h('span', { class: 'chip-dot', style: { background: this._colors[m] || 'var(--text-muted)' } }),
-        label
-      );
-      chips.appendChild(chip);
-    });
-    container.appendChild(chips);
-
-    container.appendChild(h('div', { class: 'timeline-chart', id: 'timeline-chart-container' }));
-
-    container.appendChild(h('div', { class: 'metric-cards', id: 'timeline-metrics', style: { marginBottom: '18px' } }));
-
-    container.appendChild(h('div', { class: 'section-header' }, 'Snapshots'));
-    container.appendChild(h('div', { class: 'snapshot-list', id: 'snapshot-list' }));
-
-    Shell.renderMain(container);
-    await this._loadData();
-  },
-
-  async _loadData() {
-    const snaps = State.get('snapshots') || [];
-    if (!snaps.length) {
-      this._renderSnapList([]);
-      return;
-    }
-
-    const summaries = await Promise.all(snaps.map(s => API.snapshotSummary(s.id)));
-    this._snapData = snaps.map((s, i) => {
-      const sum = summaries[i].ok && summaries[i].data ? summaries[i].data : {};
-      return {
-        ...s,
-        unit_count: sum.unit_count ?? s.unit_count ?? 0,
-        instruction_count: sum.instructions ?? (sum.metrics || {}).instruction_count ?? 0,
-        health_score: sum.health_score ?? 0,
-        warning_count: sum.warnings ?? (sum.metrics || {}).warnings ?? 0,
-        error_count: sum.errors ?? (sum.metrics || {}).errors ?? 0,
-        remark_count: sum.remarks ?? (sum.metrics || {}).remark_count ?? 0,
-        function_count: sum.functions ?? (sum.metrics || {}).function_count ?? 0,
-      };
-    });
-
-    this._renderSnapList(this._snapData);
-    this._renderMetricCards();
-    this._drawChart();
-  },
-
-  _renderMetricCards() {
-    const el = document.getElementById('timeline-metrics');
-    if (!el || !this._snapData.length) return;
-    clearEl(el);
-    const latest = this._snapData[0];
-    const metricDefs = [
-      { key: 'unit_count', label: 'Units' },
-      { key: 'instruction_count', label: 'Instructions' },
-      { key: 'health_score', label: 'Health' },
-      { key: 'remark_count', label: 'Remarks' },
-      { key: 'function_count', label: 'Functions' },
-    ];
-    metricDefs.forEach(m => {
-      const val = latest[m.key] ?? 0;
-      let delta = null, deltaCls = 'neutral';
-      if (this._snapData.length > 1) {
-        const prev = this._snapData[1];
-        const d = (latest[m.key] ?? 0) - (prev[m.key] ?? 0);
-        if (d !== 0) {
-          const sign = d > 0 ? '+' : '';
-          const isGood = m.key === 'health_score' ? d > 0 : m.key === 'warning_count' || m.key === 'error_count' ? d < 0 : null;
-          deltaCls = isGood === true ? 'improvement' : isGood === false ? 'regression' : 'neutral';
-          delta = `${sign}${formatNumber(d)} vs prev`;
-        }
-      }
-      el.appendChild(UI.metric(m.label, val, delta, deltaCls));
-    });
-  },
-
-  _drawChart() {
-    const container = document.getElementById('timeline-chart-container');
-    if (!container) return;
-    clearEl(container);
-    const data = this._snapData;
-    const svgNS = 'http://www.w3.org/2000/svg';
-    const svg = document.createElementNS(svgNS, 'svg');
-    svg.style.width = '100%';
-    svg.style.height = '220px';
-    container.appendChild(svg);
-
-    if (data.length < 2) {
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', '50%'); text.setAttribute('y', '50%');
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)'); text.setAttribute('font-size', '12');
-      text.textContent = data.length === 1 ? 'Add another snapshot to see trends' : 'Capture snapshots to see trends';
-      svg.appendChild(text);
-      return;
-    }
-
-    const w = 800, ht = 220, padL = 48, padR = 16, padT = 20, padB = 36;
-    svg.setAttribute('viewBox', `0 0 ${w} ${ht}`);
-    const chartW = w - padL - padR;
-    const chartH = ht - padT - padB;
-
-    // Horizontal grid lines
-    for (let i = 0; i <= 4; i++) {
-      const y = padT + (chartH * i / 4);
-      const line = document.createElementNS(svgNS, 'line');
-      line.setAttribute('x1', padL); line.setAttribute('y1', y);
-      line.setAttribute('x2', w - padR); line.setAttribute('y2', y);
-      line.setAttribute('stroke', 'rgba(142,142,147,0.12)');
-      line.setAttribute('stroke-width', '1');
-      svg.appendChild(line);
-    }
-
-    const xStep = chartW / (data.length - 1);
-
-    this._metrics.forEach(m => {
-      const values = data.map(s => Number(s[m]) || 0);
-      const max = Math.max(...values, 1);
-      const min = Math.min(...values, 0);
-      const range = max - min || 1;
-      const color = this._colors[m] || 'var(--accent)';
-
-      const points = data.map((_, i) => {
-        const x = padL + i * xStep;
-        const y = padT + chartH - ((values[i] - min) / range) * chartH;
-        return `${x.toFixed(1)},${y.toFixed(1)}`;
-      });
-
-      // Area fill
-      const areaPoints = `${padL},${padT + chartH} ${points.join(' ')} ${(padL + (data.length - 1) * xStep).toFixed(1)},${padT + chartH}`;
-      const area = document.createElementNS(svgNS, 'polygon');
-      area.setAttribute('points', areaPoints);
-      area.setAttribute('fill', color);
-      area.setAttribute('opacity', '0.08');
-      svg.appendChild(area);
-
-      const poly = document.createElementNS(svgNS, 'polyline');
-      poly.setAttribute('points', points.join(' '));
-      poly.setAttribute('fill', 'none');
-      poly.setAttribute('stroke', color);
-      poly.setAttribute('stroke-width', '2');
-      poly.setAttribute('stroke-linejoin', 'round');
-      svg.appendChild(poly);
-
-      data.forEach((_, i) => {
-        const [x, y] = points[i].split(',');
-        const circle = document.createElementNS(svgNS, 'circle');
-        circle.setAttribute('cx', x); circle.setAttribute('cy', y);
-        circle.setAttribute('r', '3.5'); circle.setAttribute('fill', color);
-        svg.appendChild(circle);
-      });
-
-      // Y-axis labels for first metric only
-      if (m === this._metrics[0]) {
-        for (let i = 0; i <= 4; i++) {
-          const val = min + (range * (4 - i) / 4);
-          const y = padT + (chartH * i / 4);
-          const text = document.createElementNS(svgNS, 'text');
-          text.setAttribute('x', String(padL - 6));
-          text.setAttribute('y', String(y + 3));
-          text.setAttribute('text-anchor', 'end');
-          text.setAttribute('fill', 'var(--fg3)');
-          text.setAttribute('font-size', '9');
-          text.setAttribute('font-family', 'var(--mono)');
-          text.textContent = val >= 1000 ? (val / 1000).toFixed(1) + 'k' : String(Math.round(val));
-          svg.appendChild(text);
-        }
-      }
-    });
-
-    // X-axis labels
-    data.forEach((s, i) => {
-      const x = padL + i * xStep;
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', x); text.setAttribute('y', ht - 8);
-      text.setAttribute('text-anchor', 'middle');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = (s.id || '').slice(0, 6);
-      svg.appendChild(text);
-    });
-
-    // Legend
-    const legendX = w - padR - this._metrics.length * 100;
-    this._metrics.forEach((m, i) => {
-      const x = legendX + i * 100;
-      const rect = document.createElementNS(svgNS, 'rect');
-      rect.setAttribute('x', x); rect.setAttribute('y', '4');
-      rect.setAttribute('width', '8'); rect.setAttribute('height', '8');
-      rect.setAttribute('rx', '2');
-      rect.setAttribute('fill', this._colors[m] || 'var(--accent)');
-      svg.appendChild(rect);
-
-      const text = document.createElementNS(svgNS, 'text');
-      text.setAttribute('x', String(x + 12)); text.setAttribute('y', '12');
-      text.setAttribute('fill', 'var(--fg3)');
-      text.setAttribute('font-size', '9');
-      text.setAttribute('font-family', 'var(--mono)');
-      text.textContent = m.replace(/_/g, ' ');
-      svg.appendChild(text);
-    });
-  },
-
-  _renderSnapList(snaps) {
-    const el = document.getElementById('snapshot-list');
-    if (!el) return;
-    clearEl(el);
-    if (!snaps.length) {
-      el.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'No snapshots yet')));
-      return;
-    }
-    snaps.forEach((s, idx) => {
-      const healthPct = Number(s.health_score) || 0;
-      const healthCls = healthPct >= 80 ? 'excellent' : healthPct >= 60 ? 'good' : healthPct >= 40 ? 'fair' : 'poor';
-      const healthColors = { excellent: 'var(--green)', good: 'var(--teal)', fair: 'var(--orange)', poor: 'var(--red)' };
-
-      const deltas = h('div', { class: 'snap-row-deltas', style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } });
-      if (idx < snaps.length - 1) {
-        const prev = snaps[idx + 1];
-        const defs = [
-          { key: 'instruction_count', label: 'inst' },
-          { key: 'health_score', label: 'health' },
-          { key: 'unit_count', label: 'units' },
-        ];
-        defs.forEach(d => {
-          const delta = (s[d.key] || 0) - (prev[d.key] || 0);
-          if (delta !== 0) {
-            const cls = delta > 0 ? 'positive' : 'negative';
-            deltas.appendChild(h('span', { class: `snap-delta ${cls}` },
-              `${delta > 0 ? '+' : ''}${formatNumber(delta)} ${d.label}`));
-          }
-        });
-      }
-
-      el.appendChild(h('div', { class: 'snap-row', onClick: () => { State.set('currentSnapshot', s); Router.navigate('/'); } },
-        h('span', { class: 'snap-id mono' }, (s.id || '').slice(0, 8)),
-        h('span', { class: 'snap-date text-secondary' }, timeAgo(s.created_unix)),
-        h('span', { class: 'snap-root text-muted mono' }, s.source_root || '–'),
-        deltas,
-        h('span', { class: 'snap-num mono' }, formatNumber(s.unit_count || 0)),
-        h('span', { class: 'snap-health mono', style: { color: healthColors[healthCls] } },
-          healthPct > 0 ? String(Math.round(healthPct)) : '–'),
-      ));
-    });
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Insights View
-   ============================================================ */
-
-const insightEmptyReasons = {
-  call_frequency: 'Requires call graph data. Ensure IR function stats are available.',
-  header_depth: 'Requires header dependency data. Compile with -H or enable header tracking.',
-  diagnostic_delta: 'Requires at least two snapshots to compare diagnostic changes.',
-  optimization_delta: 'Requires at least two snapshots to compare optimization remarks.',
-  compilation_flow: 'Requires time-trace data. Compile with -ftime-trace.',
-  metric_trends: 'Requires IR summary data. Ensure IR bitcode files are available.',
-};
-
-const insightNeedsBaseline = new Set(['diagnostic_delta', 'optimization_delta']);
-
-const InsightsView = {
-  _running: new Set(),
-
-  async render() {
-    this._running = new Set();
-    const container = h('div', {});
-    container.appendChild(h('div', { class: 'section-header' }, 'Cross-Unit Insights'));
-    const grid = h('div', { class: 'insight-grid', id: 'insight-grid' });
-    container.appendChild(grid);
-    Shell.renderMain(container);
-
-    const snap = State.get('currentSnapshot');
-    if (!snap) {
-      grid.appendChild(h('div', { class: 'empty-state' }, h('div', {}, 'Select a snapshot first')));
-      return;
-    }
-
-    const res = await API.insights(snap.id);
-    const insights = Array.isArray(res.data) ? res.data : [];
-
-    if (!insights.length) {
-      grid.appendChild(h('div', { class: 'empty-state' },
-        h('div', {}, 'No insights available'),
-        h('div', { class: 'reason' }, res.error || 'No insights registered for this snapshot')));
-      return;
-    }
-
-    const available = insights.filter(i => i.available);
-    const unavailable = insights.filter(i => !i.available);
-
-    if (available.length) {
-      available.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, idx, snap.id));
-      });
-    }
-
-    if (unavailable.length) {
-      grid.appendChild(h('div', { class: 'insight-section-label' }, 'Requires Additional Data'));
-      unavailable.forEach((insight, idx) => {
-        grid.appendChild(this._renderInsightCard(insight, available.length + idx, snap.id));
-      });
-    }
-
-    available.forEach((insight, idx) => {
-      this._runInsight(insight, idx, snap.id);
-    });
-  },
-
-  _renderInsightCard(insight, idx, snapId) {
-    const category = CapabilityData.category(insight.required_capability || '');
-    const card = h('div', { class: 'insight-card', id: `insight-card-${idx}` },
-      h('div', { class: 'insight-title' }, titleCase(insight.name || 'Unnamed')),
-      h('div', { class: 'insight-category text-muted', style: { fontSize: '11px' } }, category),
-      h('div', { class: 'insight-desc' }, insight.description || '')
-    );
-
-    if (!insight.available) {
-      const reason = insightEmptyReasons[insight.name] || insight.reason || 'Additional data sources needed for this analysis.';
-      card.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: 'auto', paddingTop: '8px', lineHeight: '1.5' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return card;
-    }
-
-    const body = h('div', { class: 'insight-body', id: `insight-body-${idx}` });
-    body.appendChild(h('div', { class: 'insight-skeleton' }));
-    card.appendChild(body);
-    return card;
-  },
-
-  async _runInsight(insight, idx, snapId) {
-    if (this._running.has(insight.name)) return;
-    this._running.add(insight.name);
-
-    const body = document.getElementById(`insight-body-${idx}`);
-    if (!body) return;
-
-    let res = null;
-    if (insightNeedsBaseline.has(insight.name)) {
-      const snaps = State.get('snapshots') || [];
-      const curIdx = snaps.findIndex(s => s.id === snapId);
-      for (let i = curIdx + 1; i < snaps.length && !res?.ok; i++) {
-        res = await API.insight(snapId, insight.name, snaps[i].id);
-      }
-      if (!res?.ok) res = await API.insight(snapId, insight.name);
-    } else {
-      res = await API.insight(snapId, insight.name);
-    }
-    clearEl(body);
-
-    if (!res.ok) {
-      const reason = insightEmptyReasons[insight.name] || 'This insight requires additional capability data that is not yet available.';
-      body.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', lineHeight: '1.6', padding: '8px 0' } },
-        h('span', { style: { display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%', background: 'var(--fg3)', marginRight: '6px', verticalAlign: 'middle' } }),
-        reason
-      ));
-      return;
-    }
-
-    const rawData = res.data?.data || res.data;
-    if (!rawData || (typeof rawData === 'object' && Object.keys(rawData).length === 0)) {
-      body.appendChild(h('div', { class: 'empty-state', style: { minHeight: '80px' } },
-        h('div', {}, 'No data to display'),
-        h('div', { class: 'reason' }, 'This insight did not find notable patterns in the current snapshot.')));
-      return;
-    }
-
-    const rendered = this._renderInsightData(insight.name, rawData);
-    if (rendered) {
-      body.appendChild(rendered);
-    } else {
-      const normalized = CapabilityData.normalizeResults([
-        { capability: insight.required_capability || insight.name, value: rawData }
-      ])[0];
-      body.appendChild(normalized ? UI.capabilityPanel(normalized) : h('div', { class: 'text-muted', style: { fontSize: '12px' } }, 'No data returned'));
-    }
-  },
-
-  _renderInsightData(name, data) {
-    const d = data || {};
-    const wrap = h('div', { class: 'insight-content' });
-
-    if (name === 'pass_impact') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Optimization Hit Rate'), h('strong', { class: 'mono' }, `${(d.optimization_hit_rate_pct || 0).toFixed(1)}%`)));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Remarks'), h('strong', { class: 'mono' }, formatNumber(d.total_remarks || 0))));
-      const byType = d.by_type || {};
-      Object.entries(byType).forEach(([k, v]) => {
-        metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, `Type ${titleCase(k)}`), h('strong', { class: 'mono' }, formatNumber(v))));
-      });
-      wrap.appendChild(metrics);
-      if (d.by_type && Object.keys(d.by_type).length > 1) {
-        const donutData = Object.entries(d.by_type).filter(([, v]) => v > 0).map(([label, value]) => ({ label: titleCase(label), value }));
-        const donut = UI.donutChart(donutData, { size: 100 });
-        if (donut) wrap.appendChild(donut);
-      }
-      const passes = Array.isArray(d.top_passes_by_remarks) ? d.top_passes_by_remarks : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Passes By Remarks'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10), { columns: ['count', 'pass', 'pct_of_total'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'function_complexity') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Instructions'), h('strong', { class: 'mono' }, formatNumber(d.total_instructions || 0))));
-      if (d.p90_instruction_threshold) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'P90 Threshold'), h('strong', { class: 'mono' }, formatNumber(d.p90_instruction_threshold))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_instructions) ? d.top_by_instructions : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.instructions || f.basic_blocks || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'debug_info') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Debug Info'), h('strong', { class: 'mono' }, d.has_debug_info ? 'Yes' : 'No')));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Coverage'), h('strong', { class: 'mono' }, titleCase(d.coverage || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Compile Units'), h('strong', { class: 'mono' }, formatNumber(d.compile_units || 0))));
-      if (d.max_dwo_version) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'DWO Version'), h('strong', { class: 'mono' }, String(d.max_dwo_version))));
-      wrap.appendChild(metrics);
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    if (name === 'section_sizes') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Size'), h('strong', { class: 'mono' }, formatBytes(d.total_size || 0))));
-      if (d.format && !isCorruptedString(d.format)) metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Format'), h('strong', { class: 'mono' }, d.format)));
-      wrap.appendChild(metrics);
-      const cats = d.category_breakdown || {};
-      const catEntries = Object.entries(cats).filter(([k, v]) => v && v.size > 0 && !isCorruptedString(k)).sort((a, b) => b[1].size - a[1].size);
-      if (catEntries.length) {
-        const flameItems = catEntries.map(([label, v]) => ({ label: titleCase(label), value: v.size }));
-        const flame = UI.flameBars(flameItems);
-        if (flame) wrap.appendChild(flame);
-        const legend = h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '6px', fontSize: '11px' } });
-        const colors = ['#5B8DB8', '#5DB8A8', '#D4A574', '#9DB86E', '#C97DB8', '#9B7DB8', '#D48B9B', '#6EC9C4'];
-        catEntries.forEach(([label, v], i) => {
-          legend.appendChild(h('span', { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
-            h('i', { style: { width: '8px', height: '8px', borderRadius: '2px', background: colors[i % colors.length], display: 'inline-block', flexShrink: '0' } }),
-            `${titleCase(label)}: ${formatBytes(v.size)} (${(v.pct_of_total || 0).toFixed(1)}%)`
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      const sections = (Array.isArray(d.sections) ? d.sections : []).filter(s => s.name && !isCorruptedString(s.name)).slice(0, 10);
-      if (sections.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Sections'));
-        const barData = sections.map(s => ({ label: s.name, amount: s.size || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      return wrap;
-    }
-
-    if (name === 'loop_nesting') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Loops'), h('strong', { class: 'mono' }, formatNumber(d.total_loops || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.global_max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deep Nesting Threshold'), h('strong', { class: 'mono' }, String(d.deep_nesting_threshold || 3))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Deeply Nested Fns'), h('strong', { class: 'mono' }, formatNumber(d.deeply_nested_functions || 0))));
-      wrap.appendChild(metrics);
-      const fns = (Array.isArray(d.top_by_nesting) ? d.top_by_nesting : []).filter(f => f.name && !isCorruptedString(f.name));
-      if (fns.length) {
-        const barData = fns.slice(0, 8).map(f => ({ label: f.name, amount: f.loops || 0 }));
-        const chart = UI.barChart(barData);
-        if (chart) wrap.appendChild(chart);
-      }
-      return wrap;
-    }
-
-    if (name === 'diagnostic_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Error Delta'), h('strong', { class: 'mono' }, String(d.error_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Warning Delta'), h('strong', { class: 'mono' }, String(d.warning_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Note Delta'), h('strong', { class: 'mono' }, String(d.note_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Errors'), h('strong', { class: 'mono' }, String(d.new_errors || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'New Warnings'), h('strong', { class: 'mono' }, String(d.new_warnings || 0))));
-      wrap.appendChild(metrics);
-      const base = d.baseline || {};
-      const prim = d.primary || {};
-      if (base.errors != null || prim.errors != null) {
-        const items = [
-          { label: 'Errors', before: base.errors || 0, after: prim.errors || 0 },
-          { label: 'Warnings', before: base.warnings || 0, after: prim.warnings || 0 },
-          { label: 'Notes', before: base.notes || 0, after: prim.notes || 0 },
-        ];
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const newDiags = Array.isArray(d.new_diagnostics) ? d.new_diagnostics : [];
-      if (newDiags.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'New Diagnostics'));
-        wrap.appendChild(UI.findingList(newDiags.slice(0, 20)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No new diagnostics detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'optimization_delta') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Delta'), h('strong', { class: 'mono' }, String(d.total_delta || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Primary Total'), h('strong', { class: 'mono' }, formatNumber(d.primary_total || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Baseline Total'), h('strong', { class: 'mono' }, formatNumber(d.baseline_total || 0))));
-      wrap.appendChild(metrics);
-      const byType = d.by_type_delta || {};
-      const cleanEntries = Object.entries(byType).filter(([k]) => !isCorruptedString(k));
-      if (cleanEntries.length) {
-        const items = cleanEntries.map(([label, v]) => ({
-          label: titleCase(label),
-          before: v?.baseline || 0,
-          after: v?.primary || 0,
-        }));
-        const deltaBar = UI.deltaBar(items);
-        if (deltaBar) wrap.appendChild(deltaBar);
-      }
-      const passes = Array.isArray(d.top_changed_passes) ? d.top_changed_passes.filter(p => !isCorruptedString(p.pass || '')) : [];
-      if (passes.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Top Changed Passes'));
-        wrap.appendChild(UI.dataTable(passes.slice(0, 10)));
-      } else {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No significant pass-level changes detected between snapshots.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'header_depth') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Max Depth'), h('strong', { class: 'mono' }, String(d.max_depth || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Headers'), h('strong', { class: 'mono' }, formatNumber(d.total_headers || 0))));
-      wrap.appendChild(metrics);
-      const chains = Array.isArray(d.deepest_chains) ? d.deepest_chains : [];
-      if (chains.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Deepest Include Chains'));
-        wrap.appendChild(UI.dataTable(chains.slice(0, 10)));
-      }
-      const most = Array.isArray(d.most_included) ? d.most_included : [];
-      if (most.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Included Headers'));
-        wrap.appendChild(UI.dataTable(most.slice(0, 10)));
-      }
-      if (!chains.length && !most.length && !d.max_depth) {
-        wrap.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg3)', marginTop: '10px' } }, 'No header dependency data found. Compile with -H to enable.'));
-      }
-      return wrap;
-    }
-
-    if (name === 'call_frequency') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Total Functions'), h('strong', { class: 'mono' }, formatNumber(d.total_functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Call Edges'), h('strong', { class: 'mono' }, formatNumber(d.total_call_edges || 0))));
-      wrap.appendChild(metrics);
-      const fanIn = (Array.isArray(d.top_callers_by_fan_in) ? d.top_callers_by_fan_in : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanOut = (Array.isArray(d.top_callees_by_fan_out) ? d.top_callees_by_fan_out : []).filter(f => f.name && !isCorruptedString(f.name));
-      const fanInHasData = fanIn.some(f => (f.incoming_calls || 0) > 0);
-      const fanOutHasData = fanOut.some(f => (f.outgoing_calls || 0) > 0);
-      if (fanIn.length && fanInHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Most Called (Fan-In)'));
-        const barData = fanIn.slice(0, 8).map(f => ({ label: f.name, amount: f.incoming_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      if (fanOut.length && fanOutHasData) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Highest Fan-Out'));
-        const barData = fanOut.slice(0, 8).map(f => ({ label: f.name, amount: f.outgoing_calls || 0 }));
-        wrap.appendChild(UI.barChart(barData));
-      }
-      const hubs = Array.isArray(d.hub_functions) ? d.hub_functions.filter(f => f.name && !isCorruptedString(f.name)) : [];
-      if (hubs.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Hub Functions'));
-        wrap.appendChild(UI.dataTable(hubs.slice(0, 8), { columns: ['name', 'incoming_calls', 'outgoing_calls'] }));
-      }
-      if (!fanInHasData && !fanOutHasData && fanOut.length) {
-        wrap.appendChild(h('div', { style: { fontSize: '11px', color: 'var(--fg3)', marginTop: '12px', marginBottom: '6px', textTransform: 'uppercase', letterSpacing: '.5px' } }, 'Functions'));
-        wrap.appendChild(UI.dataTable(fanOut.slice(0, 10), { columns: ['name', 'outgoing_calls', 'incoming_calls'] }));
-      }
-      return wrap;
-    }
-
-    if (name === 'compilation_flow') {
-      const stages = Array.isArray(d.stages) ? d.stages : [];
-      const total = d.total_duration_ms || 0;
-      const slowest = d.slowest_event || {};
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' },
-        h('span', {}, 'Total Time'), h('strong', { class: 'mono' }, `${total} ms`)));
-      if (slowest.name) {
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Event'),
-          h('strong', { class: 'mono', style: { fontSize: '10px' } }, slowest.name)));
-        metrics.appendChild(h('div', { class: 'mini-metric' },
-          h('span', {}, 'Slowest Time'),
-          h('strong', { class: 'mono' }, `${Math.round((slowest.duration_us || 0) / 1000)} ms`)));
-      }
-      wrap.appendChild(metrics);
-      if (stages.length) {
-        const colors = { frontend: '#5B8DB8', optimizer: '#D4A574', codegen: '#9DB86E', other: '#C97DB8' };
-        // Stacked horizontal bar
-        const bar = h('div', { style: { display: 'flex', height: '28px', borderRadius: '4px', overflow: 'hidden', margin: '12px 0 4px' } });
-        stages.forEach(s => {
-          const pct = s.pct_of_total || 0;
-          if (pct <= 0) return;
-          const color = colors[s.stage] || '#9B7DB8';
-          const seg = h('div', {
-            style: { width: `${pct}%`, background: color, display: 'flex', alignItems: 'center',
-                     justifyContent: 'center', overflow: 'hidden', whiteSpace: 'nowrap' },
-            title: `${s.stage}: ${s.duration_ms} ms (${pct}%)`,
-          }, pct > 8 ? h('span', { style: { fontSize: '10px', color: '#fff', fontWeight: '600' } }, s.stage) : null);
-          bar.appendChild(seg);
-        });
-        wrap.appendChild(bar);
-        // Legend rows
-        const legend = h('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } });
-        stages.forEach(s => {
-          const color = colors[s.stage] || '#9B7DB8';
-          legend.appendChild(h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' } },
-            h('i', { style: { width: '10px', height: '10px', borderRadius: '2px', background: color, flexShrink: '0', display: 'inline-block' } }),
-            h('span', { style: { color: 'var(--fg2)', minWidth: '80px' } }, s.stage),
-            h('span', { class: 'mono' }, `${s.duration_ms} ms`),
-            h('span', { style: { color: 'var(--fg3)', marginLeft: '4px' } }, `${s.pct_of_total}%`)
-          ));
-        });
-        wrap.appendChild(legend);
-      }
-      return wrap;
-    }
-
-    if (name === 'metric_trends') {
-      const metrics = h('div', { class: 'mini-metrics' });
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Functions'), h('strong', { class: 'mono' }, formatNumber(d.functions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instructions'), h('strong', { class: 'mono' }, formatNumber(d.instructions || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Globals'), h('strong', { class: 'mono' }, formatNumber(d.globals || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Instr / Fn'), h('strong', { class: 'mono' }, String(d.instructions_per_function || 0))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Size Class'), h('strong', { class: 'mono' }, titleCase(d.size_class || 'unknown'))));
-      metrics.appendChild(h('div', { class: 'mini-metric' }, h('span', {}, 'Density'), h('strong', { class: 'mono' }, titleCase(d.density_class || 'unknown'))));
-      wrap.appendChild(metrics);
-      if (d.functions > 0 && d.instructions > 0) {
-        const donutData = [
-          { label: 'Functions', value: d.functions },
-          { label: 'Globals', value: d.globals || 0 },
-        ].filter(x => x.value > 0);
-        if (donutData.length > 1) {
-          const donut = UI.donutChart(donutData, { size: 90 });
-          if (donut) wrap.appendChild(donut);
-        }
-      }
-      const interps = Array.isArray(d.interpretations) ? d.interpretations : [];
-      if (interps.length) {
-        const list = h('div', { style: { marginTop: '10px', display: 'flex', flexDirection: 'column', gap: '6px' } });
-        interps.forEach(msg => {
-          list.appendChild(h('div', { style: { fontSize: '12px', color: 'var(--fg2)', lineHeight: '1.5', padding: '6px 10px', background: 'var(--bg2)', borderRadius: 'var(--r)', borderLeft: '3px solid var(--accent)' } }, msg));
-        });
-        wrap.appendChild(list);
-      }
-      return wrap;
-    }
-
-    return null;
-  },
-};
-
-/* ============================================================
-   LLVM Advisor — Remarks Explorer View
-   ============================================================ */
-
 const RemarksView = {
   async render() {
     const snap = State.get('currentSnapshot');

>From acdfa56d391953f14ebb9150eaa19c6c18eee1bc Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sat, 22 Aug 2026 18:04:31 +0530
Subject: [PATCH 40/41] [llvm-advisor] Trim capability maps and aggregate logic
 to remarks-only

---
 .../src/Client/HTTP/Assets/bundled.html       | 94 ++-----------------
 .../src/Client/HTTP/Assets/core.js            | 92 +-----------------
 .../src/Client/HTTP/Assets/index_html.inc     | 94 ++-----------------
 .../src/Client/HTTP/Assets/units.js           |  2 +-
 4 files changed, 18 insertions(+), 264 deletions(-)

diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
index 9a43eb2e7afd8..d21b067241009 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/bundled.html
@@ -1106,39 +1106,10 @@
 };
 
 const capabilityFriendlyNames = {
-  'llvm.ir.summary': 'IR Summary',
-  'llvm.ir.function_stats': 'IR Function Stats',
-  'llvm.ir.view': 'IR View',
-  'llvm.ir.diff': 'IR Diff',
-  'llvm.ir.passes.list': 'Pass Pipeline',
-  'clang.diag.summary': 'Diagnostics',
-  'clang.template_stats': 'Template Stats',
-  'clang.static_analysis': 'Static Analysis',
   'llvm.remarks.summary': 'Optimization Remarks',
   'llvm.remarks.detail': 'Remark Details',
-  'llvm.remarks.size_diff': 'Remark Size Diff',
-  'llvm.obj.summary': 'Binary Summary',
-  'llvm.obj.sections': 'Binary Sections',
-  'llvm.obj.symbols': 'Binary Symbols',
-  'llvm.debug.detail': 'Debug Info',
-  'llvm.debug.summary': 'Debug Summary',
-  'llvm.cfg': 'Control Flow Graph',
-  'llvm.dom_tree': 'Dominator Tree',
-  'llvm.call_graph': 'Call Graph',
-  'llvm.loop_info': 'Loop Info',
-  'llvm.selection_dag': 'Selection DAG',
-  'llvm.machine_ir': 'Machine IR',
-  'llvm.asm.view': 'Assembly',
-  'llvm.mca.report': 'Machine Code Analyzer',
-  'llvm.exegesis': 'Instruction Benchmarks',
-  'llvm.lto.summary': 'LTO Summary',
-  'llvm.lto.function_stats': 'LTO Function Stats',
-  'llvm.cgdata': 'CG Data',
-  'lld.mapfile': 'Linker Map',
-  'lld.mapfile.diff': 'Linker Map Diff',
-  'offload.binary.inspect': 'Offload Binary',
-  'runtime.correlate': 'Runtime Correlation',
-  'runtime.summary': 'Runtime Summary',
+  'llvm.remarks.relational': 'Relational Remarks',
+  'llvm.remarks.hotspot': 'Remark Hotspots',
   'build.compile_commands': 'Compile Commands',
 };
 
@@ -1275,26 +1246,15 @@
 const CapabilityData = {
   category(capability) {
     const id = String(capability || '');
+    if (id.startsWith('llvm.remarks.')) return 'Remarks';
     if (id.startsWith('build.')) return 'Build';
-    if (id.startsWith('clang.')) return 'Clang';
-    if (id.startsWith('llvm.ir.') || id === 'llvm.inlining.tree' || id.startsWith('llvm.remarks.') || id.startsWith('llvm.pass.')) return 'IR';
-    if (id.startsWith('llvm.obj.') || id.startsWith('llvm.debug.') || id === 'llvm.cgdata' || id.startsWith('lld.mapfile')) return 'Binary';
-    if (id.startsWith('llvm.cfg') || id.startsWith('llvm.dom_tree') || id.startsWith('llvm.call_graph') || id.startsWith('llvm.loop_info') || id.startsWith('llvm.selection_dag') || id.startsWith('llvm.machine_ir') || id.startsWith('llvm.asm.') || id.startsWith('llvm.mca.') || id === 'llvm.exegesis') return 'Inspection';
-    if (id.startsWith('llvm.lto.')) return 'LTO';
-    if (id.startsWith('offload.')) return 'Offload';
-    if (id.startsWith('runtime.')) return 'Runtime';
     return 'Other';
   },
 
   shouldQueryCapability(spec, scope = 'unit') {
     const id = spec?.id || spec?.capability_id || '';
     if (!id) return false;
-    if (id === 'llvm.exegesis') return false;
-    if (id === 'clang.template_stats' || id === 'clang.static_analysis') return false;
-    if (id.startsWith('runtime.')) return false;
-    if (id === 'llvm.ir.diff' || id === 'llvm.remarks.size_diff' || id === 'lld.mapfile.diff')
-      return scope === 'compare';
-    return true;
+    return id.startsWith('llvm.remarks.');
   },
 
   isAvailable(value) {
@@ -1388,13 +1348,7 @@
   aggregate(unitResults) {
     const agg = {
       units: 0,
-      instructions: 0,
-      functions: 0,
-      warnings: 0,
-      errors: 0,
       remarks: 0,
-      sections: 0,
-      symbols: 0,
       unavailable: 0,
       metrics: {},
       capabilityCoverage: new Map(),
@@ -1437,10 +1391,7 @@
         agg.familyCoverage.set(family, familyEntry);
 
         const v = result.value;
-        const trackExplicitly = new Set([
-          'instructions', 'instruction_count', 'functions', 'function_count',
-          'warnings', 'errors', 'remarks', 'remark_count',
-        ]);
+        const trackExplicitly = new Set(['remarks', 'remark_count']);
         if (result.available) {
           Object.entries(result.metrics || {}).forEach(([key, raw]) => {
             if (typeof raw !== 'number' || !Number.isFinite(raw)) return;
@@ -1453,49 +1404,16 @@
             }
           });
         }
-        if (result.capability === 'llvm.ir.summary') {
-          const inst = Number(v.instructions || v.instruction_count || 0);
-          const fns = Number(v.functions || v.function_count || 0);
-          agg.instructions += inst;
-          agg.functions += fns;
-          row.instructions = inst || row.instructions || 0;
-          row.functions = fns || row.functions || 0;
-        }
-        if (result.capability === 'llvm.ir.function_stats') {
-          const total = Array.isArray(v.functions) ? v.functions.reduce((s, f) => s + Number(f.instructions || f.instruction_count || 0), 0) : 0;
-          row.instructions = row.instructions || total;
-          agg.instructions += row.instructions && !(v.instructions || v.instruction_count) ? 0 : Number(v.instructions || v.instruction_count || 0);
-        }
-        if (result.capability === 'clang.diag.summary') {
-          agg.warnings += Number(v.warnings || 0);
-          agg.errors += Number(v.errors || 0);
-          row.warnings = Number(v.warnings || 0);
-          row.errors = Number(v.errors || 0);
-        }
         if (result.capability === 'llvm.remarks.summary') {
           const cnt = Number(v.count || v.remark_count || 0);
           agg.remarks += cnt;
           row.remarks = cnt;
         }
-        if (result.capability === 'llvm.obj.summary') {
-          agg.sections += Number(v.sections || 0);
-          agg.symbols += Number(v.symbols || v.symbol_count || 0);
-          row.sections = Number(v.sections || 0);
-          row.symbols = Number(v.symbols || v.symbol_count || 0);
-        }
       });
       rows.push(row);
     });
     agg.rows = rows;
-    // Override metrics with correctly-tracked per-capability values to avoid
-    // double-counting (e.g. 'functions' from IR vs debug/AST capabilities).
-    if (agg.instructions) agg.metrics.instructions = agg.instructions;
-    if (agg.functions) agg.metrics.functions = agg.functions;
     if (agg.remarks) agg.metrics.remarks = agg.remarks;
-    if (agg.warnings) agg.metrics.warnings = agg.warnings;
-    if (agg.errors) agg.metrics.errors = agg.errors;
-    delete agg.metrics.instruction_count;
-    delete agg.metrics.function_count;
     delete agg.metrics.remark_count;
     agg.capabilities = Array.from(agg.capabilityCoverage.values()).sort((a, b) =>
       a.family === b.family ? a.capability.localeCompare(b.capability) : a.family.localeCompare(b.family)
@@ -2995,7 +2913,7 @@
     }
     const [res, metrics] = await Promise.all([
       API.units(snap.id),
-      API.querySnapshot(snap.id, ['llvm.ir.summary', 'clang.diag.summary', 'llvm.obj.summary', 'llvm.remarks.summary']),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary', 'llvm.remarks.detail']),
     ]);
     const units = Array.isArray(res.data) ? res.data : [];
     const byId = new Map();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
index 8d22e354161a4..43de78f9b7dc9 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/core.js
@@ -369,39 +369,10 @@ const isCorruptedString = (s) => {
 };
 
 const capabilityFriendlyNames = {
-  'llvm.ir.summary': 'IR Summary',
-  'llvm.ir.function_stats': 'IR Function Stats',
-  'llvm.ir.view': 'IR View',
-  'llvm.ir.diff': 'IR Diff',
-  'llvm.ir.passes.list': 'Pass Pipeline',
-  'clang.diag.summary': 'Diagnostics',
-  'clang.template_stats': 'Template Stats',
-  'clang.static_analysis': 'Static Analysis',
   'llvm.remarks.summary': 'Optimization Remarks',
   'llvm.remarks.detail': 'Remark Details',
-  'llvm.remarks.size_diff': 'Remark Size Diff',
-  'llvm.obj.summary': 'Binary Summary',
-  'llvm.obj.sections': 'Binary Sections',
-  'llvm.obj.symbols': 'Binary Symbols',
-  'llvm.debug.detail': 'Debug Info',
-  'llvm.debug.summary': 'Debug Summary',
-  'llvm.cfg': 'Control Flow Graph',
-  'llvm.dom_tree': 'Dominator Tree',
-  'llvm.call_graph': 'Call Graph',
-  'llvm.loop_info': 'Loop Info',
-  'llvm.selection_dag': 'Selection DAG',
-  'llvm.machine_ir': 'Machine IR',
-  'llvm.asm.view': 'Assembly',
-  'llvm.mca.report': 'Machine Code Analyzer',
-  'llvm.exegesis': 'Instruction Benchmarks',
-  'llvm.lto.summary': 'LTO Summary',
-  'llvm.lto.function_stats': 'LTO Function Stats',
-  'llvm.cgdata': 'CG Data',
-  'lld.mapfile': 'Linker Map',
-  'lld.mapfile.diff': 'Linker Map Diff',
-  'offload.binary.inspect': 'Offload Binary',
-  'runtime.correlate': 'Runtime Correlation',
-  'runtime.summary': 'Runtime Summary',
+  'llvm.remarks.relational': 'Relational Remarks',
+  'llvm.remarks.hotspot': 'Remark Hotspots',
   'build.compile_commands': 'Compile Commands',
 };
 
@@ -538,26 +509,15 @@ const ignoredMetricKeys = new Set([
 const CapabilityData = {
   category(capability) {
     const id = String(capability || '');
+    if (id.startsWith('llvm.remarks.')) return 'Remarks';
     if (id.startsWith('build.')) return 'Build';
-    if (id.startsWith('clang.')) return 'Clang';
-    if (id.startsWith('llvm.ir.') || id === 'llvm.inlining.tree' || id.startsWith('llvm.remarks.') || id.startsWith('llvm.pass.')) return 'IR';
-    if (id.startsWith('llvm.obj.') || id.startsWith('llvm.debug.') || id === 'llvm.cgdata' || id.startsWith('lld.mapfile')) return 'Binary';
-    if (id.startsWith('llvm.cfg') || id.startsWith('llvm.dom_tree') || id.startsWith('llvm.call_graph') || id.startsWith('llvm.loop_info') || id.startsWith('llvm.selection_dag') || id.startsWith('llvm.machine_ir') || id.startsWith('llvm.asm.') || id.startsWith('llvm.mca.') || id === 'llvm.exegesis') return 'Inspection';
-    if (id.startsWith('llvm.lto.')) return 'LTO';
-    if (id.startsWith('offload.')) return 'Offload';
-    if (id.startsWith('runtime.')) return 'Runtime';
     return 'Other';
   },
 
   shouldQueryCapability(spec, scope = 'unit') {
     const id = spec?.id || spec?.capability_id || '';
     if (!id) return false;
-    if (id === 'llvm.exegesis') return false;
-    if (id === 'clang.template_stats' || id === 'clang.static_analysis') return false;
-    if (id.startsWith('runtime.')) return false;
-    if (id === 'llvm.ir.diff' || id === 'llvm.remarks.size_diff' || id === 'lld.mapfile.diff')
-      return scope === 'compare';
-    return true;
+    return id.startsWith('llvm.remarks.');
   },
 
   isAvailable(value) {
@@ -651,13 +611,7 @@ const CapabilityData = {
   aggregate(unitResults) {
     const agg = {
       units: 0,
-      instructions: 0,
-      functions: 0,
-      warnings: 0,
-      errors: 0,
       remarks: 0,
-      sections: 0,
-      symbols: 0,
       unavailable: 0,
       metrics: {},
       capabilityCoverage: new Map(),
@@ -700,10 +654,7 @@ const CapabilityData = {
         agg.familyCoverage.set(family, familyEntry);
 
         const v = result.value;
-        const trackExplicitly = new Set([
-          'instructions', 'instruction_count', 'functions', 'function_count',
-          'warnings', 'errors', 'remarks', 'remark_count',
-        ]);
+        const trackExplicitly = new Set(['remarks', 'remark_count']);
         if (result.available) {
           Object.entries(result.metrics || {}).forEach(([key, raw]) => {
             if (typeof raw !== 'number' || !Number.isFinite(raw)) return;
@@ -716,49 +667,16 @@ const CapabilityData = {
             }
           });
         }
-        if (result.capability === 'llvm.ir.summary') {
-          const inst = Number(v.instructions || v.instruction_count || 0);
-          const fns = Number(v.functions || v.function_count || 0);
-          agg.instructions += inst;
-          agg.functions += fns;
-          row.instructions = inst || row.instructions || 0;
-          row.functions = fns || row.functions || 0;
-        }
-        if (result.capability === 'llvm.ir.function_stats') {
-          const total = Array.isArray(v.functions) ? v.functions.reduce((s, f) => s + Number(f.instructions || f.instruction_count || 0), 0) : 0;
-          row.instructions = row.instructions || total;
-          agg.instructions += row.instructions && !(v.instructions || v.instruction_count) ? 0 : Number(v.instructions || v.instruction_count || 0);
-        }
-        if (result.capability === 'clang.diag.summary') {
-          agg.warnings += Number(v.warnings || 0);
-          agg.errors += Number(v.errors || 0);
-          row.warnings = Number(v.warnings || 0);
-          row.errors = Number(v.errors || 0);
-        }
         if (result.capability === 'llvm.remarks.summary') {
           const cnt = Number(v.count || v.remark_count || 0);
           agg.remarks += cnt;
           row.remarks = cnt;
         }
-        if (result.capability === 'llvm.obj.summary') {
-          agg.sections += Number(v.sections || 0);
-          agg.symbols += Number(v.symbols || v.symbol_count || 0);
-          row.sections = Number(v.sections || 0);
-          row.symbols = Number(v.symbols || v.symbol_count || 0);
-        }
       });
       rows.push(row);
     });
     agg.rows = rows;
-    // Override metrics with correctly-tracked per-capability values to avoid
-    // double-counting (e.g. 'functions' from IR vs debug/AST capabilities).
-    if (agg.instructions) agg.metrics.instructions = agg.instructions;
-    if (agg.functions) agg.metrics.functions = agg.functions;
     if (agg.remarks) agg.metrics.remarks = agg.remarks;
-    if (agg.warnings) agg.metrics.warnings = agg.warnings;
-    if (agg.errors) agg.metrics.errors = agg.errors;
-    delete agg.metrics.instruction_count;
-    delete agg.metrics.function_count;
     delete agg.metrics.remark_count;
     agg.capabilities = Array.from(agg.capabilityCoverage.values()).sort((a, b) =>
       a.family === b.family ? a.capability.localeCompare(b.capability) : a.family.localeCompare(b.family)
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
index 9c804bf1b7b27..6b76feae7c99a 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/index_html.inc
@@ -1109,39 +1109,10 @@ const isCorruptedString = (s) => {
 };
 
 const capabilityFriendlyNames = {
-  'llvm.ir.summary': 'IR Summary',
-  'llvm.ir.function_stats': 'IR Function Stats',
-  'llvm.ir.view': 'IR View',
-  'llvm.ir.diff': 'IR Diff',
-  'llvm.ir.passes.list': 'Pass Pipeline',
-  'clang.diag.summary': 'Diagnostics',
-  'clang.template_stats': 'Template Stats',
-  'clang.static_analysis': 'Static Analysis',
   'llvm.remarks.summary': 'Optimization Remarks',
   'llvm.remarks.detail': 'Remark Details',
-  'llvm.remarks.size_diff': 'Remark Size Diff',
-  'llvm.obj.summary': 'Binary Summary',
-  'llvm.obj.sections': 'Binary Sections',
-  'llvm.obj.symbols': 'Binary Symbols',
-  'llvm.debug.detail': 'Debug Info',
-  'llvm.debug.summary': 'Debug Summary',
-  'llvm.cfg': 'Control Flow Graph',
-  'llvm.dom_tree': 'Dominator Tree',
-  'llvm.call_graph': 'Call Graph',
-  'llvm.loop_info': 'Loop Info',
-  'llvm.selection_dag': 'Selection DAG',
-  'llvm.machine_ir': 'Machine IR',
-  'llvm.asm.view': 'Assembly',
-  'llvm.mca.report': 'Machine Code Analyzer',
-  'llvm.exegesis': 'Instruction Benchmarks',
-  'llvm.lto.summary': 'LTO Summary',
-  'llvm.lto.function_stats': 'LTO Function Stats',
-  'llvm.cgdata': 'CG Data',
-  'lld.mapfile': 'Linker Map',
-  'lld.mapfile.diff': 'Linker Map Diff',
-  'offload.binary.inspect': 'Offload Binary',
-  'runtime.correlate': 'Runtime Correlation',
-  'runtime.summary': 'Runtime Summary',
+  'llvm.remarks.relational': 'Relational Remarks',
+  'llvm.remarks.hotspot': 'Remark Hotspots',
   'build.compile_commands': 'Compile Commands',
 };
 
@@ -1278,26 +1249,15 @@ const ignoredMetricKeys = new Set([
 const CapabilityData = {
   category(capability) {
     const id = String(capability || '');
+    if (id.startsWith('llvm.remarks.')) return 'Remarks';
     if (id.startsWith('build.')) return 'Build';
-    if (id.startsWith('clang.')) return 'Clang';
-    if (id.startsWith('llvm.ir.') || id === 'llvm.inlining.tree' || id.startsWith('llvm.remarks.') || id.startsWith('llvm.pass.')) return 'IR';
-    if (id.startsWith('llvm.obj.') || id.startsWith('llvm.debug.') || id === 'llvm.cgdata' || id.startsWith('lld.mapfile')) return 'Binary';
-    if (id.startsWith('llvm.cfg') || id.startsWith('llvm.dom_tree') || id.startsWith('llvm.call_graph') || id.startsWith('llvm.loop_info') || id.startsWith('llvm.selection_dag') || id.startsWith('llvm.machine_ir') || id.startsWith('llvm.asm.') || id.startsWith('llvm.mca.') || id === 'llvm.exegesis') return 'Inspection';
-    if (id.startsWith('llvm.lto.')) return 'LTO';
-    if (id.startsWith('offload.')) return 'Offload';
-    if (id.startsWith('runtime.')) return 'Runtime';
     return 'Other';
   },
 
   shouldQueryCapability(spec, scope = 'unit') {
     const id = spec?.id || spec?.capability_id || '';
     if (!id) return false;
-    if (id === 'llvm.exegesis') return false;
-    if (id === 'clang.template_stats' || id === 'clang.static_analysis') return false;
-    if (id.startsWith('runtime.')) return false;
-    if (id === 'llvm.ir.diff' || id === 'llvm.remarks.size_diff' || id === 'lld.mapfile.diff')
-      return scope === 'compare';
-    return true;
+    return id.startsWith('llvm.remarks.');
   },
 
   isAvailable(value) {
@@ -1391,13 +1351,7 @@ const CapabilityData = {
   aggregate(unitResults) {
     const agg = {
       units: 0,
-      instructions: 0,
-      functions: 0,
-      warnings: 0,
-      errors: 0,
       remarks: 0,
-      sections: 0,
-      symbols: 0,
       unavailable: 0,
       metrics: {},
       capabilityCoverage: new Map(),
@@ -1440,10 +1394,7 @@ const CapabilityData = {
         agg.familyCoverage.set(family, familyEntry);
 
         const v = result.value;
-        const trackExplicitly = new Set([
-          'instructions', 'instruction_count', 'functions', 'function_count',
-          'warnings', 'errors', 'remarks', 'remark_count',
-        ]);
+        const trackExplicitly = new Set(['remarks', 'remark_count']);
         if (result.available) {
           Object.entries(result.metrics || {}).forEach(([key, raw]) => {
             if (typeof raw !== 'number' || !Number.isFinite(raw)) return;
@@ -1456,49 +1407,16 @@ const CapabilityData = {
             }
           });
         }
-        if (result.capability === 'llvm.ir.summary') {
-          const inst = Number(v.instructions || v.instruction_count || 0);
-          const fns = Number(v.functions || v.function_count || 0);
-          agg.instructions += inst;
-          agg.functions += fns;
-          row.instructions = inst || row.instructions || 0;
-          row.functions = fns || row.functions || 0;
-        }
-        if (result.capability === 'llvm.ir.function_stats') {
-          const total = Array.isArray(v.functions) ? v.functions.reduce((s, f) => s + Number(f.instructions || f.instruction_count || 0), 0) : 0;
-          row.instructions = row.instructions || total;
-          agg.instructions += row.instructions && !(v.instructions || v.instruction_count) ? 0 : Number(v.instructions || v.instruction_count || 0);
-        }
-        if (result.capability === 'clang.diag.summary') {
-          agg.warnings += Number(v.warnings || 0);
-          agg.errors += Number(v.errors || 0);
-          row.warnings = Number(v.warnings || 0);
-          row.errors = Number(v.errors || 0);
-        }
         if (result.capability === 'llvm.remarks.summary') {
           const cnt = Number(v.count || v.remark_count || 0);
           agg.remarks += cnt;
           row.remarks = cnt;
         }
-        if (result.capability === 'llvm.obj.summary') {
-          agg.sections += Number(v.sections || 0);
-          agg.symbols += Number(v.symbols || v.symbol_count || 0);
-          row.sections = Number(v.sections || 0);
-          row.symbols = Number(v.symbols || v.symbol_count || 0);
-        }
       });
       rows.push(row);
     });
     agg.rows = rows;
-    // Override metrics with correctly-tracked per-capability values to avoid
-    // double-counting (e.g. 'functions' from IR vs debug/AST capabilities).
-    if (agg.instructions) agg.metrics.instructions = agg.instructions;
-    if (agg.functions) agg.metrics.functions = agg.functions;
     if (agg.remarks) agg.metrics.remarks = agg.remarks;
-    if (agg.warnings) agg.metrics.warnings = agg.warnings;
-    if (agg.errors) agg.metrics.errors = agg.errors;
-    delete agg.metrics.instruction_count;
-    delete agg.metrics.function_count;
     delete agg.metrics.remark_count;
     agg.capabilities = Array.from(agg.capabilityCoverage.values()).sort((a, b) =>
       a.family === b.family ? a.capability.localeCompare(b.capability) : a.family.localeCompare(b.family)
@@ -2998,7 +2916,7 @@ const UnitsView = {
     }
     const [res, metrics] = await Promise.all([
       API.units(snap.id),
-      API.querySnapshot(snap.id, ['llvm.ir.summary', 'clang.diag.summary', 'llvm.obj.summary', 'llvm.remarks.summary']),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary', 'llvm.remarks.detail']),
     ]);
     const units = Array.isArray(res.data) ? res.data : [];
     const byId = new Map();
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/units.js b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/units.js
index b652e840baf84..9c93fe1474871 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/units.js
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/Assets/units.js
@@ -93,7 +93,7 @@ const UnitsView = {
     }
     const [res, metrics] = await Promise.all([
       API.units(snap.id),
-      API.querySnapshot(snap.id, ['llvm.ir.summary', 'clang.diag.summary', 'llvm.obj.summary', 'llvm.remarks.summary']),
+      API.querySnapshot(snap.id, ['llvm.remarks.summary', 'llvm.remarks.detail']),
     ]);
     const units = Array.isArray(res.data) ? res.data : [];
     const byId = new Map();

>From dbda8ab9b0b36494a14f1b49d4543aab23cb56bb Mon Sep 17 00:00:00 2001
From: kamini08 <kaminibanait03 at gmail.com>
Date: Sun, 23 Aug 2026 06:44:29 +0530
Subject: [PATCH 41/41] [llvm-advisor] Add lit tests for remarks ingestion,
 queries, compare, and HTTP endpoints

---
 llvm/test/lit.cfg.py                          |   1 +
 .../llvm-advisor/Inputs/demangle.opt.yaml     | 104 +++
 .../llvm-advisor/Inputs/example.opt.yaml      | 773 ++++++++++++++++++
 .../llvm-advisor/Inputs/invalid.opt.yaml      |   1 +
 .../llvm-advisor/Inputs/src/demangle.cpp      |  12 +
 .../tools/llvm-advisor/Inputs/src/example.c   |  18 +
 .../Inputs/test_http_endpoints.py             | 229 ++++++
 .../tools/llvm-advisor/compare-remarks.test   |  12 +
 .../test/tools/llvm-advisor/import-basic.test |   9 +
 .../tools/llvm-advisor/import-errors.test     |   8 +
 .../import-infer-source-root.test             |   7 +
 .../tools/llvm-advisor/import-invalid.test    |   6 +
 .../tools/llvm-advisor/query-demangle.test    |  11 +
 .../tools/llvm-advisor/query-hotspot.test     |  10 +
 .../tools/llvm-advisor/query-relational.test  |  13 +
 .../tools/llvm-advisor/server-endpoints.test  |   3 +
 .../src/Client/HTTP/HTTPServer.cpp            |  13 +-
 17 files changed, 1228 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/demangle.opt.yaml
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/example.opt.yaml
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/invalid.opt.yaml
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/src/demangle.cpp
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/src/example.c
 create mode 100644 llvm/test/tools/llvm-advisor/Inputs/test_http_endpoints.py
 create mode 100644 llvm/test/tools/llvm-advisor/compare-remarks.test
 create mode 100644 llvm/test/tools/llvm-advisor/import-basic.test
 create mode 100644 llvm/test/tools/llvm-advisor/import-errors.test
 create mode 100644 llvm/test/tools/llvm-advisor/import-infer-source-root.test
 create mode 100644 llvm/test/tools/llvm-advisor/import-invalid.test
 create mode 100644 llvm/test/tools/llvm-advisor/query-demangle.test
 create mode 100644 llvm/test/tools/llvm-advisor/query-hotspot.test
 create mode 100644 llvm/test/tools/llvm-advisor/query-relational.test
 create mode 100644 llvm/test/tools/llvm-advisor/server-endpoints.test

diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index 09df1e3fd6281..7e225c2103274 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -325,6 +325,7 @@ def get_asan_rtlib():
         "sancov",
         "sanstats",
         "llvm-remarkutil",
+        "llvm-advisor",
     ]
 )
 
diff --git a/llvm/test/tools/llvm-advisor/Inputs/demangle.opt.yaml b/llvm/test/tools/llvm-advisor/Inputs/demangle.opt.yaml
new file mode 100644
index 0000000000000..699ae3ead6416
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/demangle.opt.yaml
@@ -0,0 +1,104 @@
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: 'src/demangle.cpp', Line: 11, Column: 12 }
+Function:        _Z5entryii
+Args:
+  - String:          ''''
+  - Callee:          _ZN2ns10Calculator3addEii
+    DebugLoc:        { File: 'src/demangle.cpp', Line: 4, Column: 0 }
+  - String:          ''' inlined into '''
+  - Caller:          _Z5entryii
+    DebugLoc:        { File: 'src/demangle.cpp', Line: 9, Column: 0 }
+  - String:          ''''
+  - String:          ' with '
+  - String:          '(cost='
+  - Cost:            '-40'
+  - String:          ', threshold='
+  - Threshold:       '337'
+  - String:          ')'
+  - String:          ' at callsite '
+  - String:          entry
+  - String:          ':'
+  - Line:            '2'
+  - String:          ':'
+  - Column:          '12'
+  - String:          ';'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: 'src/demangle.cpp', Line: 11, Column: 26 }
+Function:        _Z5entryii
+Args:
+  - String:          ''''
+  - Callee:          _ZN2ns10Calculator3mulEii
+    DebugLoc:        { File: 'src/demangle.cpp', Line: 5, Column: 0 }
+  - String:          ''' inlined into '''
+  - Caller:          _Z5entryii
+    DebugLoc:        { File: 'src/demangle.cpp', Line: 9, Column: 0 }
+  - String:          ''''
+  - String:          ' with '
+  - String:          '(cost='
+  - Cost:            '-40'
+  - String:          ', threshold='
+  - Threshold:       '337'
+  - String:          ')'
+  - String:          ' at callsite '
+  - String:          entry
+  - String:          ':'
+  - Line:            '2'
+  - String:          ':'
+  - Column:          '26'
+  - String:          ';'
+...
+--- !Missed
+Pass:            slp-vectorizer
+Name:            NotPossible
+DebugLoc:        { File: 'src/demangle.cpp', Line: 5, Column: 36 }
+Function:        _Z5entryii
+Args:
+  - String:          'Cannot SLP vectorize list: vectorization was impossible'
+  - String:          ' with available vectorization factors'
+...
+--- !Analysis
+Pass:            prologepilog
+Name:            StackSize
+DebugLoc:        { File: 'src/demangle.cpp', Line: 9, Column: 0 }
+Function:        _Z5entryii
+Args:
+  - NumStackBytes:   '0'
+  - String:          ' stack bytes in function '''
+  - Function:        _Z5entryii
+  - String:          ''''
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        _Z5entryii
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          IMUL32rr
+  - String:          ': '
+  - INST_IMUL32rr:   '2'
+  - String:          "\n"
+  - String:          LEA64_32r
+  - String:          ': '
+  - INST_LEA64_32r:  '1'
+  - String:          "\n"
+  - String:          RET64
+  - String:          ': '
+  - INST_RET64:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionCount
+DebugLoc:        { File: 'src/demangle.cpp', Line: 9, Column: 0 }
+Function:        _Z5entryii
+Args:
+  - NumInstructions: '4'
+  - String:          ' instructions in function'
+...
diff --git a/llvm/test/tools/llvm-advisor/Inputs/example.opt.yaml b/llvm/test/tools/llvm-advisor/Inputs/example.opt.yaml
new file mode 100644
index 0000000000000..6dc2eb265f78a
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/example.opt.yaml
@@ -0,0 +1,773 @@
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 14 }
+Function:        sum_of_squares
+Args:
+  - String:          ''''
+  - Callee:          square
+  - String:          ''' inlined into '''
+  - Caller:          sum_of_squares
+    DebugLoc:        { File: 'src/example.c', Line: 5, Column: 0 }
+  - String:          ''''
+  - String:          ' with '
+  - String:          '(cost='
+  - Cost:            '-15030'
+  - String:          ', threshold='
+  - Threshold:       '337'
+  - String:          ')'
+  - String:          ' at callsite '
+  - String:          sum_of_squares
+  - String:          ':'
+  - Line:            '3'
+  - String:          ':'
+  - Column:          '14'
+  - String:          ';'
+...
+--- !Passed
+Pass:            inline
+Name:            Inlined
+DebugLoc:        { File: 'src/example.c', Line: 14, Column: 15 }
+Function:        normalize
+Args:
+  - String:          ''''
+  - Callee:          sum_of_squares
+    DebugLoc:        { File: 'src/example.c', Line: 5, Column: 0 }
+  - String:          ''' inlined into '''
+  - Caller:          normalize
+    DebugLoc:        { File: 'src/example.c', Line: 12, Column: 0 }
+  - String:          ''''
+  - String:          ' with '
+  - String:          '(cost='
+  - Cost:            '0'
+  - String:          ', threshold='
+  - Threshold:       '225'
+  - String:          ')'
+  - String:          ' at callsite '
+  - String:          normalize
+  - String:          ':'
+  - Line:            '2'
+  - String:          ':'
+  - Column:          '15'
+  - String:          ';'
+...
+--- !Passed
+Pass:            loop-vectorize
+Name:            Vectorized
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        sum_of_squares
+Args:
+  - String:          'vectorized '
+  - String:          ''
+  - String:          'loop (vectorization width: '
+  - VectorizationFactor: '4'
+  - String:          ', interleaved count: '
+  - InterleaveCount: '2'
+  - String:          ')'
+...
+--- !Missed
+Pass:            slp-vectorizer
+Name:            NotPossible
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        sum_of_squares
+Args:
+  - String:          'Cannot SLP vectorize list: vectorization was impossible'
+  - String:          ' with available vectorization factors'
+...
+--- !Passed
+Pass:            loop-vectorize
+Name:            Vectorized
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'vectorized '
+  - String:          ''
+  - String:          'loop (vectorization width: '
+  - VectorizationFactor: '4'
+  - String:          ', interleaved count: '
+  - InterleaveCount: '2'
+  - String:          ')'
+...
+--- !Missed
+Pass:            loop-vectorize
+Name:            VectorizationNotBeneficial
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          the cost-model indicates that vectorization is not beneficial
+...
+--- !Missed
+Pass:            loop-vectorize
+Name:            InterleavingNotBeneficial
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          the cost-model indicates that interleaving is not beneficial
+...
+--- !Missed
+Pass:            slp-vectorizer
+Name:            NotPossible
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        normalize
+Args:
+  - String:          'Cannot SLP vectorize list: vectorization was impossible'
+  - String:          ' with available vectorization factors'
+...
+--- !Passed
+Pass:            loop-unroll
+Name:            PartialUnrolled
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'unrolled loop by a factor of '
+  - UnrollCount:     '2'
+  - String:          ' with run-time trip count'
+...
+--- !Missed
+Pass:            regalloc
+Name:            SpillReloadCopies
+DebugLoc:        { File: 'src/example.c', Line: 5, Column: 1 }
+Function:        sum_of_squares
+Args:
+  - NumVRCopies:     '1'
+  - String:          ' virtual registers copies '
+  - TotalCopiesCost: '3.125000e-01'
+  - String:          ' total copies cost '
+  - String:          generated in function
+...
+--- !Analysis
+Pass:            prologepilog
+Name:            StackSize
+DebugLoc:        { File: 'src/example.c', Line: 5, Column: 0 }
+Function:        sum_of_squares
+Args:
+  - NumStackBytes:   '0'
+  - String:          ' stack bytes in function '''
+  - Function:        sum_of_squares
+  - String:          ''''
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 24 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+  - String:          TEST64rr
+  - String:          ': '
+  - INST_TEST64rr:   '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CMP64ri32
+  - String:          ': '
+  - INST_CMP64ri32:  '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '2'
+  - String:          "\n"
+  - String:          JMP_1
+  - String:          ': '
+  - INST_JMP_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          RET64
+  - String:          ': '
+  - INST_RET64:      '1'
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PXORrr
+  - String:          ': '
+  - INST_PXORrr:     '2'
+  - String:          "\n"
+  - String:          AND64ri32
+  - String:          ': '
+  - INST_AND64ri32:  '1'
+  - String:          "\n"
+  - String:          MOV64rr
+  - String:          ': '
+  - INST_MOV64rr:    '1'
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PSHUFDri
+  - String:          ': '
+  - INST_PSHUFDri:   '6'
+  - String:          "\n"
+  - String:          PMULUDQrr
+  - String:          ': '
+  - INST_PMULUDQrr:  '4'
+  - String:          "\n"
+  - String:          MOVDQUrm
+  - String:          ': '
+  - INST_MOVDQUrm:   '2'
+  - String:          "\n"
+  - String:          PADDDrr
+  - String:          ': '
+  - INST_PADDDrr:    '2'
+  - String:          "\n"
+  - String:          PUNPCKLDQrr
+  - String:          ': '
+  - INST_PUNPCKLDQrr: '2'
+  - String:          "\n"
+  - String:          ADD64ri32
+  - String:          ': '
+  - INST_ADD64ri32:  '1'
+  - String:          "\n"
+  - String:          CMP64rr
+  - String:          ': '
+  - INST_CMP64rr:    '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PADDDrr
+  - String:          ': '
+  - INST_PADDDrr:    '3'
+  - String:          "\n"
+  - String:          PSHUFDri
+  - String:          ': '
+  - INST_PSHUFDri:   '2'
+  - String:          "\n"
+  - String:          JMP_1
+  - String:          ': '
+  - INST_JMP_1:      '1'
+  - String:          "\n"
+  - String:          MOVPDI2DIrr
+  - String:          ': '
+  - INST_MOVPDI2DIrr: '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          ADD32rr
+  - String:          ': '
+  - INST_ADD32rr:    '1'
+  - String:          "\n"
+  - String:          IMUL32rr
+  - String:          ': '
+  - INST_IMUL32rr:   '1'
+  - String:          "\n"
+  - String:          INC64r
+  - String:          ': '
+  - INST_INC64r:     '1'
+  - String:          "\n"
+  - String:          MOV32rm
+  - String:          ': '
+  - INST_MOV32rm:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 0 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CMP64rr
+  - String:          ': '
+  - INST_CMP64rr:    '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 9, Column: 3 }
+Function:        sum_of_squares
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          RET64
+  - String:          ': '
+  - INST_RET64:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionCount
+DebugLoc:        { File: 'src/example.c', Line: 5, Column: 0 }
+Function:        sum_of_squares
+Args:
+  - NumInstructions: '47'
+  - String:          ' instructions in function'
+...
+--- !Missed
+Pass:            regalloc
+Name:            SpillReloadCopies
+DebugLoc:        { File: 'src/example.c', Line: 12, Column: 1 }
+Function:        normalize
+Args:
+  - NumVRCopies:     '2'
+  - String:          ' virtual registers copies '
+  - TotalCopiesCost: '5.078125e-01'
+  - String:          ' total copies cost '
+  - String:          generated in function
+...
+--- !Analysis
+Pass:            prologepilog
+Name:            StackSize
+DebugLoc:        { File: 'src/example.c', Line: 12, Column: 0 }
+Function:        normalize
+Args:
+  - NumStackBytes:   '0'
+  - String:          ' stack bytes in function '''
+  - Function:        normalize
+  - String:          ''''
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 13, Column: 9 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+  - String:          TEST64rr
+  - String:          ': '
+  - INST_TEST64rr:   '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CMP64ri32
+  - String:          ': '
+  - INST_CMP64ri32:  '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '2'
+  - String:          "\n"
+  - String:          JMP_1
+  - String:          ': '
+  - INST_JMP_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PXORrr
+  - String:          ': '
+  - INST_PXORrr:     '2'
+  - String:          "\n"
+  - String:          AND64ri32
+  - String:          ': '
+  - INST_AND64ri32:  '1'
+  - String:          "\n"
+  - String:          MOV64rr
+  - String:          ': '
+  - INST_MOV64rr:    '1'
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PSHUFDri
+  - String:          ': '
+  - INST_PSHUFDri:   '6'
+  - String:          "\n"
+  - String:          PMULUDQrr
+  - String:          ': '
+  - INST_PMULUDQrr:  '4'
+  - String:          "\n"
+  - String:          MOVDQUrm
+  - String:          ': '
+  - INST_MOVDQUrm:   '2'
+  - String:          "\n"
+  - String:          PADDDrr
+  - String:          ': '
+  - INST_PADDDrr:    '2'
+  - String:          "\n"
+  - String:          PUNPCKLDQrr
+  - String:          ': '
+  - INST_PUNPCKLDQrr: '2'
+  - String:          "\n"
+  - String:          ADD64ri32
+  - String:          ': '
+  - INST_ADD64ri32:  '1'
+  - String:          "\n"
+  - String:          CMP64rr
+  - String:          ': '
+  - INST_CMP64rr:    '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          PADDDrr
+  - String:          ': '
+  - INST_PADDDrr:    '3'
+  - String:          "\n"
+  - String:          PSHUFDri
+  - String:          ': '
+  - INST_PSHUFDri:   '2'
+  - String:          "\n"
+  - String:          JMP_1
+  - String:          ': '
+  - INST_JMP_1:      '1'
+  - String:          "\n"
+  - String:          MOVPDI2DIrr
+  - String:          ': '
+  - INST_MOVPDI2DIrr: '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 8, Column: 21 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          ADD32rr
+  - String:          ': '
+  - INST_ADD32rr:    '1'
+  - String:          "\n"
+  - String:          IMUL32rr
+  - String:          ': '
+  - INST_IMUL32rr:   '1'
+  - String:          "\n"
+  - String:          INC64r
+  - String:          ': '
+  - INST_INC64r:     '1'
+  - String:          "\n"
+  - String:          MOV32rm
+  - String:          ': '
+  - INST_MOV32rm:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 7, Column: 0 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CMP64rr
+  - String:          ': '
+  - INST_CMP64rr:    '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 15, Column: 13 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+  - String:          TEST32rr
+  - String:          ': '
+  - INST_TEST32rr:   '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CMP64ri32
+  - String:          ': '
+  - INST_CMP64ri32:  '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          JMP_1
+  - String:          ': '
+  - INST_JMP_1:      '1'
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          AND64ri32
+  - String:          ': '
+  - INST_AND64ri32:  '1'
+  - String:          "\n"
+  - String:          MOV64rr
+  - String:          ': '
+  - INST_MOV64rr:    '1'
+  - String:          "\n"
+  - String:          XOR32rr
+  - String:          ': '
+  - INST_XOR32rr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 17, Column: 22 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CDQ
+  - String:          ': '
+  - INST_CDQ:        '2'
+  - String:          "\n"
+  - String:          IDIV32r
+  - String:          ': '
+  - INST_IDIV32r:    '2'
+  - String:          "\n"
+  - String:          IMUL32rmi
+  - String:          ': '
+  - INST_IMUL32rmi:  '2'
+  - String:          "\n"
+  - String:          MOV32mr
+  - String:          ': '
+  - INST_MOV32mr:    '2'
+  - String:          "\n"
+  - String:          ADD64ri32
+  - String:          ': '
+  - INST_ADD64ri32:  '1'
+  - String:          "\n"
+  - String:          CMP64rr
+  - String:          ': '
+  - INST_CMP64rr:    '1'
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 16, Column: 3 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          JCC_1
+  - String:          ': '
+  - INST_JCC_1:      '1'
+  - String:          "\n"
+  - String:          TEST8ri
+  - String:          ': '
+  - INST_TEST8ri:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 17, Column: 22 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          CDQ
+  - String:          ': '
+  - INST_CDQ:        '1'
+  - String:          "\n"
+  - String:          IDIV32r
+  - String:          ': '
+  - INST_IDIV32r:    '1'
+  - String:          "\n"
+  - String:          IMUL32rmi
+  - String:          ': '
+  - INST_IMUL32rmi:  '1'
+  - String:          "\n"
+  - String:          MOV32mr
+  - String:          ': '
+  - INST_MOV32mr:    '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionMix
+DebugLoc:        { File: 'src/example.c', Line: 18, Column: 1 }
+Function:        normalize
+Args:
+  - String:          'BasicBlock: '
+  - BasicBlock:      ''
+  - String:          "\n"
+  - String:          RET64
+  - String:          ': '
+  - INST_RET64:      '1'
+  - String:          "\n"
+...
+--- !Analysis
+Pass:            asm-printer
+Name:            InstructionCount
+DebugLoc:        { File: 'src/example.c', Line: 12, Column: 0 }
+Function:        normalize
+Args:
+  - NumInstructions: '71'
+  - String:          ' instructions in function'
+...
diff --git a/llvm/test/tools/llvm-advisor/Inputs/invalid.opt.yaml b/llvm/test/tools/llvm-advisor/Inputs/invalid.opt.yaml
new file mode 100644
index 0000000000000..30346bc1fd404
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/invalid.opt.yaml
@@ -0,0 +1 @@
+not a valid remark file
diff --git a/llvm/test/tools/llvm-advisor/Inputs/src/demangle.cpp b/llvm/test/tools/llvm-advisor/Inputs/src/demangle.cpp
new file mode 100644
index 0000000000000..c1c47eb7242a4
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/src/demangle.cpp
@@ -0,0 +1,12 @@
+namespace ns {
+class Calculator {
+public:
+  int add(int a, int b) { return a + b; }
+  int mul(int a, int b) { return a * b; }
+};
+}
+
+int entry(int x, int y) {
+  ns::Calculator c;
+  return c.add(x, y) * c.mul(x, y);
+}
diff --git a/llvm/test/tools/llvm-advisor/Inputs/src/example.c b/llvm/test/tools/llvm-advisor/Inputs/src/example.c
new file mode 100644
index 0000000000000..ae6501ada55c4
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/src/example.c
@@ -0,0 +1,18 @@
+#include <stddef.h>
+
+static int square(int x) { return x * x; }
+
+int sum_of_squares(const int *arr, size_t n) {
+  int total = 0;
+  for (size_t i = 0; i < n; ++i)
+    total += square(arr[i]);
+  return total;
+}
+
+void normalize(int *arr, size_t n) {
+  if (n == 0) return;
+  int total = sum_of_squares(arr, n);
+  if (total == 0) return;
+  for (size_t i = 0; i < n; ++i)
+    arr[i] = (arr[i] * 100) / total;
+}
diff --git a/llvm/test/tools/llvm-advisor/Inputs/test_http_endpoints.py b/llvm/test/tools/llvm-advisor/Inputs/test_http_endpoints.py
new file mode 100644
index 0000000000000..079162c7b55f5
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/Inputs/test_http_endpoints.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+"""Integration test for llvm-advisor HTTP endpoints added by the remarks work."""
+
+import json
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import urllib.request
+import urllib.error
+
+
+def main():
+    if len(sys.argv) < 5:
+        print("usage: test_http_endpoints.py <llvm-advisor> <opt.yaml> <source-root> <capability-dir>", file=sys.stderr)
+        sys.exit(1)
+
+    advisor = sys.argv[1]
+    yaml_path = sys.argv[2]
+    source_root = sys.argv[3]
+    cap_dir = sys.argv[4]
+
+    store = tempfile.mkdtemp(prefix="advisor-lit-")
+
+    # Import the base remark file.
+    subprocess.run(
+        [advisor, "import", yaml_path, "--store", store, "--source-root", source_root, "--capability-dir", cap_dir],
+        check=True,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        text=True,
+    )
+
+    # Import a second (candidate) remark file so compare has differences.
+    # Sleep briefly so the two imports get distinct snapshot IDs.
+    cand_path = os.path.join(os.path.dirname(yaml_path), "demangle.opt.yaml")
+    if os.path.exists(cand_path):
+        time.sleep(1)
+        subprocess.run(
+            [advisor, "import", cand_path, "--store", store, "--source-root", source_root, "--capability-dir", cap_dir],
+            check=True,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            text=True,
+        )
+
+    # Start server on an ephemeral port.
+    proc = subprocess.Popen(
+        [advisor, "serve", "--store", store, "--port", "0", "--capability-dir", cap_dir],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        text=True,
+    )
+
+    port = None
+    for _ in range(50):
+        line = proc.stderr.readline()
+        if line:
+            m = re.search(r"listening on 127\.0\.0\.1:(\d+)", line)
+            if m:
+                port = int(m.group(1))
+                break
+        time.sleep(0.1)
+
+    if port is None:
+        proc.kill()
+        proc.wait()
+        print("server did not report port", file=sys.stderr)
+        print("stderr:", proc.stderr.read(), file=sys.stderr)
+        sys.exit(1)
+
+    base = f"http://127.0.0.1:{port}/api/v1"
+    errors = []
+
+    def get(path, expect_status=200):
+        url = base + path
+        try:
+            with urllib.request.urlopen(url, timeout=10) as resp:
+                data = resp.read().decode("utf-8")
+                if resp.status != expect_status:
+                    errors.append(f"{url}: expected {expect_status}, got {resp.status}")
+                return data
+        except urllib.error.HTTPError as e:
+            if e.code != expect_status:
+                errors.append(f"{url}: expected {expect_status}, got {e.code}")
+            return e.read().decode("utf-8")
+
+    # Health endpoint.
+    health = json.loads(get("/health"))
+    if not health.get("data", {}).get("ok"):
+        errors.append("health endpoint returned ok=false")
+
+    # Capabilities should include the remarks capabilities.
+    caps = json.loads(get("/capabilities"))
+    cap_ids = {c["id"] for c in caps.get("data", [])}
+    expected_caps = {
+        "llvm.remarks.summary",
+        "llvm.remarks.detail",
+        "llvm.remarks.relational",
+        "llvm.remarks.hotspot",
+    }
+    if not expected_caps.issubset(cap_ids):
+        errors.append(f"missing capabilities: {expected_caps - cap_ids}")
+
+    # Identify base (example) and candidate (demangle) snapshots by source files.
+    snaps = json.loads(get("/snapshots"))
+    snap_list = snaps.get("data", [])
+    if len(snap_list) < 2:
+        errors.append(f"expected >=2 snapshots, got {len(snap_list)}")
+        base_id = cand_id = None
+    else:
+        base_id = cand_id = None
+        for snap in snap_list:
+            sid = snap.get("id")
+            files_data = json.loads(get(f"/snapshots/{sid}/files")).get("data", [])
+            paths = {f.get("path") for f in files_data}
+            if "src/example.c" in paths and base_id is None:
+                base_id = sid
+            if "src/demangle.cpp" in paths and cand_id is None:
+                cand_id = sid
+        if base_id is None:
+            errors.append("could not find snapshot containing src/example.c")
+        if cand_id is None:
+            errors.append("could not find snapshot containing src/demangle.cpp")
+
+    # Relational endpoint on the base snapshot.
+    if base_id:
+        rel = json.loads(get(f"/snapshots/{base_id}/remarks/relational?limit=50"))
+        rel_data = rel.get("data", {})
+        if rel_data.get("count", 0) != 41:
+            errors.append(f"expected 41 relational rows, got {rel_data.get('count')}")
+        rel_strings = rel_data.get("strings", {})
+        if "normalize" not in rel_strings.get("function", []):
+            errors.append("'normalize' not in relational function strings")
+        if "sum_of_squares" not in rel_strings.get("function", []):
+            errors.append("'sum_of_squares' not in relational function strings")
+
+        # Relational filtering by pass.
+        rel_pass = json.loads(get(f"/snapshots/{base_id}/remarks/relational?pass=inline&limit=50"))
+        if rel_pass.get("data", {}).get("count", 0) != 2:
+            errors.append("relational pass filter did not return 2 rows")
+        if "Inlined" not in rel_pass.get("data", {}).get("strings", {}).get("name", []):
+            errors.append("relational pass filter missing Inlined")
+
+        # Relational filtering by function.
+        from urllib.parse import quote
+        rel_fn = json.loads(get(f"/snapshots/{base_id}/remarks/relational?function={quote('normalize')}&limit=50"))
+        if rel_fn.get("data", {}).get("count", 0) == 0:
+            errors.append("relational function filter returned 0 rows")
+
+    # Compare aggregate endpoint.
+    if base_id and cand_id:
+        cmp_agg = json.loads(get(f"/compare/{base_id}/{cand_id}"))
+        cmp_agg_data = cmp_agg.get("data", {})
+        if "match_summary" not in cmp_agg_data:
+            errors.append("compare aggregate missing match_summary")
+
+    # Compare function detail endpoint for a function only in the candidate.
+    if base_id and cand_id:
+        from urllib.parse import quote
+        cmp_fn = json.loads(get(f"/compare/{base_id}/{cand_id}/remarks/{quote('entry(int, int)')}"))
+        cmp_fn_data = cmp_fn.get("data", {})
+        if cmp_fn_data.get("function") != "entry(int, int)":
+            errors.append("compare function detail returned wrong function")
+        if cmp_fn_data.get("after_total", 0) == 0:
+            errors.append("compare function detail candidate total is zero")
+        if not cmp_fn_data.get("added"):
+            errors.append("compare function detail missing added entries for candidate-only function")
+
+    # Source files endpoint on the base snapshot.
+    file_paths = []
+    if base_id:
+        files = json.loads(get(f"/snapshots/{base_id}/files"))
+        file_paths = [f["path"] for f in files.get("data", [])]
+        if "src/example.c" not in file_paths:
+            errors.append("source files missing src/example.c")
+
+    # Source content endpoint.
+    if base_id and file_paths:
+        from urllib.parse import quote
+        src = json.loads(get(f"/source?path={quote('src/example.c')}&snapshot_id={base_id}"))
+        if "content" not in src.get("data", {}):
+            errors.append("source endpoint missing content")
+
+        # Source remarks endpoint.
+        src_remarks = json.loads(get(f"/source/remarks?path={quote('src/example.c')}&snapshot_id={base_id}"))
+        if "remarks" not in src_remarks.get("data", {}):
+            errors.append("source/remarks endpoint missing remarks")
+
+        # Source remarks filtering by pass.
+        src_remarks_pass = json.loads(get(f"/source/remarks?path={quote('src/example.c')}&snapshot_id={base_id}&pass=prologepilog"))
+        sr_pass_data = src_remarks_pass.get("data", {})
+        if "remarks" not in sr_pass_data:
+            errors.append("source/remarks pass filter missing remarks")
+        else:
+            pass_names = {r.get("pass") for r in sr_pass_data["remarks"]}
+            if pass_names != {"prologepilog"}:
+                errors.append(f"source/remarks pass filter returned passes {pass_names}")
+
+    # Compare remarks endpoint.
+    if base_id and cand_id:
+        cmp = json.loads(get(f"/compare/{base_id}/{cand_id}/remarks?offset=0&limit=10"))
+        if "total" not in cmp.get("data", {}):
+            errors.append("compare/remarks endpoint missing total")
+
+    # Stop server.
+    proc.terminate()
+    try:
+        proc.wait(timeout=5)
+    except subprocess.TimeoutExpired:
+        proc.kill()
+        proc.wait()
+
+    shutil.rmtree(store, ignore_errors=True)
+
+    if errors:
+        print("FAIL:")
+        for e in errors:
+            print("  -", e)
+        sys.exit(1)
+
+    print("PASS")
+
+
+if __name__ == "__main__":
+    main()
diff --git a/llvm/test/tools/llvm-advisor/compare-remarks.test b/llvm/test/tools/llvm-advisor/compare-remarks.test
new file mode 100644
index 0000000000000..118898370dc48
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/compare-remarks.test
@@ -0,0 +1,12 @@
+# Test snapshot compare via the CLI.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/example.opt.yaml >/dev/null 2>&1
+# RUN: llvm-advisor compare --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --before latest --after latest 2>&1 | FileCheck %s
+
+# CHECK: "base_snapshot_id":
+# CHECK: "candidate_snapshot_id":
+# CHECK: "match_summary":{
+# CHECK: "added":0
+# CHECK: "matched":1
+# CHECK: "unit_changes":[
+# CHECK: "match_type":"matched"
diff --git a/llvm/test/tools/llvm-advisor/import-basic.test b/llvm/test/tools/llvm-advisor/import-basic.test
new file mode 100644
index 0000000000000..42d00996fc254
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/import-basic.test
@@ -0,0 +1,9 @@
+# Test basic standalone remarks import creates a snapshot and unit.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/example.opt.yaml 2>&1 | FileCheck %s --check-prefix=CREATE
+# RUN: llvm-advisor list --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store | FileCheck %s --check-prefix=SNAPS
+# RUN: llvm-advisor list --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --snapshot latest --store %t.store | FileCheck %s --check-prefix=UNITS
+
+# CREATE: Snapshot {{[0-9a-f]+}} created — 1 file(s)
+# SNAPS: {{[0-9a-f]+}} {{.*}}/Inputs
+# UNITS: {{[0-9a-f]+}} unknown      example.opt
diff --git a/llvm/test/tools/llvm-advisor/import-errors.test b/llvm/test/tools/llvm-advisor/import-errors.test
new file mode 100644
index 0000000000000..3517d091245d0
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/import-errors.test
@@ -0,0 +1,8 @@
+# Test import error handling for missing and empty remark files.
+# RUN: rm -rf %t.store
+# RUN: not llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/does-not-exist.opt.yaml 2>&1 | FileCheck %s --check-prefix=MISSING
+# RUN: %python -c "open('%t.empty', 'w').close()"
+# RUN: not llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %t.empty 2>&1 | FileCheck %s --check-prefix=EMPTY
+
+# MISSING: remark file does not exist:
+# EMPTY: contains no remarks
diff --git a/llvm/test/tools/llvm-advisor/import-infer-source-root.test b/llvm/test/tools/llvm-advisor/import-infer-source-root.test
new file mode 100644
index 0000000000000..6a15e1b386fb1
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/import-infer-source-root.test
@@ -0,0 +1,7 @@
+# Test that import infers the source root from remark paths when none is given.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities %S/Inputs/example.opt.yaml --store %t.store 2>&1 | FileCheck %s --check-prefix=CREATE
+# RUN: llvm-advisor list --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store | FileCheck %s --check-prefix=INFEROOT
+
+# CREATE: Snapshot {{[0-9a-f]+}} created — 1 file(s)
+# INFEROOT: {{[0-9a-f]+}} {{.*}}/Inputs
diff --git a/llvm/test/tools/llvm-advisor/import-invalid.test b/llvm/test/tools/llvm-advisor/import-invalid.test
new file mode 100644
index 0000000000000..ee3b4dcd6a261
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/import-invalid.test
@@ -0,0 +1,6 @@
+# Test import error handling for a malformed remark file.
+# RUN: rm -rf %t.store
+# RUN: not llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/invalid.opt.yaml 2>&1 | FileCheck %s
+
+# CHECK: failed to parse remark file
+# CHECK: Automatic detection of remark format failed
diff --git a/llvm/test/tools/llvm-advisor/query-demangle.test b/llvm/test/tools/llvm-advisor/query-demangle.test
new file mode 100644
index 0000000000000..f292e451bde09
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/query-demangle.test
@@ -0,0 +1,11 @@
+# Test that C++ mangled names in remarks are demangled in relational output.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/demangle.opt.yaml >/dev/null 2>&1
+# RUN: llvm-advisor query --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --snapshot latest --capability llvm.remarks.relational 2>&1 | FileCheck %s
+
+# CHECK: "capability":"llvm.remarks.relational"
+# CHECK: "count":6
+# CHECK-DAG: "file":["src/demangle.cpp"]
+# CHECK-DAG: "function":["entry(int, int)"]
+# CHECK-DAG: "pass":["inline"
+# CHECK-DAG: "name":["Inlined"
diff --git a/llvm/test/tools/llvm-advisor/query-hotspot.test b/llvm/test/tools/llvm-advisor/query-hotspot.test
new file mode 100644
index 0000000000000..e802b7a144ccf
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/query-hotspot.test
@@ -0,0 +1,10 @@
+# Test llvm.remarks.hotspot aggregation for a real C example.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/example.opt.yaml >/dev/null 2>&1
+# RUN: llvm-advisor query --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --snapshot latest --capability llvm.remarks.hotspot 2>&1 | FileCheck %s
+
+# CHECK: "capability":"llvm.remarks.hotspot"
+# CHECK: "count":15
+# CHECK: "hotspots":[
+# CHECK-DAG: "function":"sum_of_squares"
+# CHECK-DAG: "function":"normalize"
diff --git a/llvm/test/tools/llvm-advisor/query-relational.test b/llvm/test/tools/llvm-advisor/query-relational.test
new file mode 100644
index 0000000000000..a391f123f9828
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/query-relational.test
@@ -0,0 +1,13 @@
+# Test llvm.remarks.relational output schema for a real C example.
+# RUN: rm -rf %t.store
+# RUN: llvm-advisor import --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --source-root %S/Inputs %S/Inputs/example.opt.yaml >/dev/null 2>&1
+# RUN: llvm-advisor query --capability-dir %llvm_src_root/tools/llvm-advisor/config/capabilities --store %t.store --snapshot latest --capability llvm.remarks.relational 2>&1 | FileCheck %s
+
+# CHECK: "capability":"llvm.remarks.relational"
+# CHECK-DAG: "schema_version":1
+# CHECK-DAG: "count":41
+# CHECK: "strings":{
+# CHECK-DAG: "function":["sum_of_squares","normalize"]
+# CHECK-DAG: "file":["src/example.c"]
+# CHECK-DAG: "pass":["inline","loop-vectorize","slp-vectorizer","loop-unroll","regalloc","prologepilog","asm-printer"]
+# CHECK-DAG: "name":["Inlined","Vectorized","NotPossible","VectorizationNotBeneficial","InterleavingNotBeneficial","PartialUnrolled","SpillReloadCopies","StackSize","InstructionMix","InstructionCount"]
diff --git a/llvm/test/tools/llvm-advisor/server-endpoints.test b/llvm/test/tools/llvm-advisor/server-endpoints.test
new file mode 100644
index 0000000000000..d018be0fb2320
--- /dev/null
+++ b/llvm/test/tools/llvm-advisor/server-endpoints.test
@@ -0,0 +1,3 @@
+# Test the HTTP endpoints added by the remarks work.
+# RUN: rm -rf %t.store
+# RUN: %python %S/Inputs/test_http_endpoints.py llvm-advisor %S/Inputs/example.opt.yaml %S/Inputs %llvm_src_root/tools/llvm-advisor/config/capabilities
diff --git a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
index b033914482590..33a3c8e98b5c4 100644
--- a/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
+++ b/llvm/tools/llvm-advisor/src/Client/HTTP/HTTPServer.cpp
@@ -1544,8 +1544,7 @@ void HTTPServer::shutdown() {
 // --- Server Run ---
 
 Error llvm::advisor::HTTPServer::run() {
-  if (Port == 0)
-    return createStringError(inconvertibleErrorCode(), "invalid port");
+  // Port 0 is allowed: the OS will assign an ephemeral port and we log it.
 
   // Load optional auth token from environment
   if (const char *EnvTok = std::getenv("LLVM_ADVISOR_TOKEN"))
@@ -1578,6 +1577,16 @@ Error llvm::advisor::HTTPServer::run() {
                              std::strerror(errno));
   }
 
+  // Log the actual bound port so tests can discover it when port 0 is used.
+  {
+    sockaddr_in BoundAddr{};
+    socklen_t BoundLen = sizeof(BoundAddr);
+    if (::getsockname(ListenFD, reinterpret_cast<sockaddr *>(&BoundAddr),
+                      &BoundLen) == 0)
+      errs() << formatv("llvm-advisor HTTP server listening on 127.0.0.1:{0}\n",
+                        ntohs(BoundAddr.sin_port));
+  }
+
   // Self-pipe for graceful shutdown
   if (::pipe(PipeFD) != 0) {
     ::close(ListenFD);



More information about the llvm-branch-commits mailing list