🏗 Architecture Flow image 1 · before → after → data structures
Walk top-down: what existed, what replaced it, and the data structures connecting the two.
flowchart TB
subgraph BEFORE["① 🔴 BEFORE — single-mode, fat wire format"]
direction LR
SP1[Static Profiler] --> CT1[CallTreeNode
intrinsics × every position]:::removed
CT1 --> J1[JSON ~9.83 MB]:::removed
LS1[LiveScan UI] -. no correlation .-> CT1
OB1[events.Broadcaster
single global stream]:::removed
end
subgraph AFTER["② 🟢 AFTER — correlated live↔static, compact wire"]
direction LR
SP2[Static Profiler] --> FR[Frame
intrinsics once per symbol]:::added
FR --> CT2[CallTreeNode
position fields only]:::modified
CT2 --> J2[JSON ~3.9 MB · −60%]:::added
LS2[LiveScan UI
+ OverviewBar + StoryStrip]:::modified --> IDX[Static Scan Index]:::added
IDX --> PA[PathAlias
container→host]:::added
PA --> FJ[FuzzyJoin · 7 tiers]:::added
FJ --> JR[JoinReport]:::added
JR -. confidence-ranked .-> LS2
OB2[pubsub.Bus + wsbroker
per-topic routing]:::added
end
subgraph DS["③ 📦 DATA STRUCTURES INVOLVED"]
direction LR
D1["Frame v1.2
new · internal
symbol-intrinsics
stored once"]:::dsnew
D2["CallTreeNode v1.2
modified · internal
position fields only"]:::dsmod
D3["FrameIntrinsics
new · write path
carrier struct,
stamped to Frame"]:::dsnew
D4["StaticNode
new · join seam
flat symbol list
scanner ↔ matcher"]:::dsnew
D5["PathAlias
new · join
(container → host)
heuristic mapping"]:::dsnew
D6["JoinReport
new · out → UI
confidence-ranked
correlations"]:::dsnew
D7["pubsub.Payload
new · internal
raw JSON,
shape-agnostic"]:::dsnew
D1 --- D2 --- D3
D4 --- D5 --- D6 --- D7
end
BEFORE -.evolves to.-> AFTER
AFTER -.uses.-> DS
classDef added fill:#238636,stroke:#3fb950,color:#fff,stroke-width:2px
classDef removed fill:#da3633,stroke:#f85149,color:#fff,stroke-width:2px
classDef modified fill:#9e6a03,stroke:#d29922,color:#fff,stroke-width:2px
classDef dsnew fill:#1c2128,stroke:#3fb950,color:#e6edf3,stroke-width:1px
classDef dsmod fill:#1c2128,stroke:#d29922,color:#e6edf3,stroke-width:1px
🧭 High-Level Business Logic image 2 · product context
Why this PR exists. Dashed box = the slice this PR touches.
flowchart TD
Dev((👤 Developer)) --> Install[Install Drift agent
in service / container]
Install --> Live[📡 Live sampling
function frequency · memory · CPU]
Install --> Static[🔍 Static scan
AST → call graph → SARIF / DOT]
Live --> UI[LiveScan UI
icicle + flamegraph]:::scope
Static --> Index[Static Scan Index]:::scope
UI --> Join{{Live ↔ Static
FuzzyJoin · 7 tiers}}:::scope
Index --> Join
Join --> Insight[🎯 Correlated insight:
this hot frame = THIS source function]:::scope
Insight --> Action[Developer optimizes,
refactors, deploys]
classDef scope fill:#1c2128,stroke:#d29922,stroke-width:3px,stroke-dasharray:6 4,color:#e6edf3
style Dev fill:#1f6feb,stroke:#2f81f7,color:#fff
style Action fill:#238636,stroke:#3fb950,color:#fff
/app/orders.py → /Users/me/proj/orders.py). The result: the desktop UI can now highlight where in source the currently-hot frame lives.
📊 Business Value Report image 3 · money · customer · runtime · runtime UX
Four-axis impact scoring. Each axis shows direction (% up/down) plus estimated $ cost vs $ profit.
🎯 PR Value Card
% change · ▲ improvement · ▼ regression↳ drift.dev/docs/value-card — how the four axes are computed
💡 Code Suggestions 3 above threshold · click to accept
Each suggestion includes a real documentation or issue link. Only suggestions above confidence threshold (0.75) are shown.
Why it matters: pagerank == 0.0 is a valid value for isolated nodes (no callers, no callees). The function treats 0.0 as "not set on Frame" and falls back to the node's value — also 0.0 — so today the output is accidentally correct. The next engineer who adds an f64 intrinsic where 0.0 is meaningful will copy this pattern and ship silent wrong output.
Requires Frame.pagerank to become Option<f64> and FrameIntrinsics.pagerank similarly.
Why it matters: The doc comment says "the FIRST call for a given frame wins" but stamp_intrinsics fires unconditionally whenever intrinsics.is_empty() is false. If two tree positions carry different pagerank values for the same symbol (PageRank is computed per-entry-point context), the last serialized tree wins — not the first.
Why it matters: The function returns (accepted int, firstSoftErr error). Any HTTP handler that does n, err := w.AppendNDJSON(r); if err != nil { http.Error(w, ..., 400) } will return 400 even when n > 0 valid lines were already written to disk — causing the client to retry a partially-accepted batch. The signature pushes error-type disambiguation onto every caller.
🧭 Visual Summary risks · key files · at-a-glance
Risks plotted by severity × likelihood. Key files as a hot-touch mindmap. Glanceable instead of scannable.
⚠️ Risks · severity ↑ × likelihood →
quadrantChart
title Risk Map
x-axis Low likelihood --> High likelihood
y-axis Low severity --> High severity
quadrant-1 Act before merge
quadrant-2 Monitor closely
quadrant-3 Acceptable
quadrant-4 Document & ship
"PR size · 100 files": [0.85, 0.90]
"Schema v1.2 compat": [0.55, 0.70]
"Pub/sub drop-overflow": [0.65, 0.65]
"Log bus lagged subs": [0.70, 0.55]
"Tier-7 fuzzy matches": [0.45, 0.50]
"PathAlias heuristic": [0.50, 0.45]
"Win CLI installer stub": [0.30, 0.55]
"First-wins not enforced": [0.40, 0.45]
"No CLI binary tests": [0.55, 0.25]
🗂 Key files · hot-touch mindmap
mindmap root((PR #36
hot files)) (Wire format) compact.rs Schema v1.2 (Live↔Static join) join_commands.rs core logic path_alias.rs heuristic (Observability) pubsub/bus.go per-topic wsbroker.go Phoenix verbs (Desktop UI) LiveScan.tsx entry point log_bus.rs call init first!
↳ drift.dev/docs/review/visual-summary — how these charts are computed
Generated by drift-review · PR #36 · refactorlab/drift · 2026-05-25
Connects live runtime sampling with static code analysis into one correlated view. Also: schema v1.2 shrinks scan output 60%, new pub/sub layer replaces the global broadcaster, and a standalone CLI binary is shipped.
Big PR — sorry. Headline feature is the live↔static join. /cc @schuldi1