gabriel / musehub public
blame.html html
315 lines 13.9 KB
Raw
sha256:7281683f5c41e5d88b6d8811fbdafebd3e01a0c9dcd90975cfcb444ba71e8e81 docs: add local source-of-truth for musehub#225, #226, #227… Sonnet 5 1 day ago
1 {% extends "musehub/base.html" %}
2
3 {% block title %}{{ owner }}/{{ repo_slug }} — blame/{{ short_ref }}/{{ short_path }}{% endblock %}
4
5 {% block breadcrumb %}
6 <a href="/{{ owner }}">{{ owner }}</a> /
7 <a href="/{{ owner }}/{{ repo_slug }}">{{ repo_slug }}</a> /
8 blame /
9 <a href="/{{ owner }}/{{ repo_slug }}/tree/{{ ref }}">{{ short_ref }}</a> /
10 {{ short_path }}
11 {% endblock %}
12
13 {% block repo_nav %}{% include "musehub/partials/repo_nav.html" %}{% endblock %}
14 {% block body_class %}app-shell{% endblock %}
15
16 {% block content %}
17
18 {# ── Page header ──────────────────────────────────────────────────────────── #}
19 <div class="blm-page-header">
20 <div class="blm-header-left">
21 <div class="blm-path-icon">
22 {{ icon("clock-circle", 18) }}
23 </div>
24 <div class="blm-path-info">
25 <h1 class="blm-filename">
26 <code>{{ short_path }}</code>
27 <span class="blm-type-badge blm-type-{{ blame_type }}">
28 {%- if blame_type == "symbol" -%}symbol-level
29 {%- else -%}file-level
30 {%- endif -%}
31 </span>
32 </h1>
33 <p class="blm-breadcrumb">
34 at <code>{{ short_ref }}</code>
35 <span>&middot;</span>
36 <a class="blm-breadcrumb-link" href="{{ base_url }}/blob/{{ ref }}/{{ path }}">View file &#8599;</a>
37 {% if blame_type in ("symbol", "file") %}
38 <span>&middot;</span>
39 <a class="blm-breadcrumb-link" href="{{ base_url }}/intel">Intel &#8599;</a>
40 {% endif %}
41 </p>
42 </div>
43 </div>
44 <div style="flex-shrink:0;margin-top:6px">
45 <a href="{{ base_url }}/commits" class="btn btn-secondary btn-sm">History</a>
46 </div>
47 </div>
48
49 {# ── Stats strip ──────────────────────────────────────────────────────────── #}
50 <div class="blm-stats">
51 <div class="blm-stat">
52 <span class="blm-stat-val">{{ total_entries | fmtnum }}</span>
53 <span>
54 {%- if blame_type == "symbol" -%}symbols
55 {%- else -%}files
56 {%- endif -%}
57 </span>
58 </div>
59 <div class="blm-stat">
60 <span class="blm-stat-val">{{ commits_in_view | length }}</span>
61 <span>commits</span>
62 </div>
63 {% if blame_type in ("symbol", "file") %}
64 <div class="blm-stat blm-stat--hotspot {% if intel_hotspot_count > 0 %}blm-stat--active{% endif %}">
65 <span class="blm-stat-val">{{ intel_hotspot_count }}</span>
66 <span>{{ icon("flame", 11) }} hotspots</span>
67 </div>
68 <div class="blm-stat blm-stat--dead {% if intel_dead_count > 0 %}blm-stat--active{% endif %}">
69 <span class="blm-stat-val">{{ intel_dead_count }}</span>
70 <span>🧊 dead</span>
71 </div>
72 <div class="blm-stat blm-stat--blast {% if intel_blast_count > 0 %}blm-stat--active{% endif %}">
73 <span class="blm-stat-val">{{ intel_blast_count }}</span>
74 <span>💥 blast risk</span>
75 </div>
76 {% endif %}
77 </div>
78
79 {# ── Empty state ──────────────────────────────────────────────────────────── #}
80 {% if not blame_entries %}
81 <div class="blm-empty">
82 {{ icon("clock-circle", 32, "icon--light-stroke") }}
83 <p>No blame data found for <code>{{ path }}</code></p>
84 {% if blame_type == "symbol" %}
85 <p class="blm-empty-hint">This file has not been indexed yet. Push a commit to trigger indexing.</p>
86 {% else %}
87 <p class="blm-empty-hint">Check that the path exists at ref <code>{{ short_ref }}</code>.</p>
88 {% endif %}
89 </div>
90
91 {% else %}
92
93 {# ── Blame layout ─────────────────────────────────────────────────────────── #}
94 <div class="blm-layout">
95
96 {# ── Left: commit legend (sticky) ──────────────────────────────────────── #}
97 <aside class="blm-legend">
98 <div class="blm-legend-hdr">
99 <span>Commits</span>
100 <span class="blm-legend-prov-key">
101 <span title="AI agent">{{ icon("agent-sm", 10) }}</span> agent
102 &nbsp;·&nbsp;
103 <span title="Human">{{ icon("user-sm", 10) }}</span> human
104 </span>
105 </div>
106 {% for c in commits_in_view %}
107 <a class="blm-commit-card" href="{{ base_url }}/commits/{{ c.commit_id }}">
108 <span class="blm-commit-dot" style="background:{{ commit_color[c.commit_id] }}"></span>
109 <div class="blm-commit-body">
110 <div class="blm-commit-top">
111 <code class="blm-commit-sha">{{ c.short_id }}</code>
112 {% if c.is_agent %}
113 <span class="blm-commit-prov blm-commit-prov--agent" title="{{ c.model_id or c.agent_id }}">
114 {{ icon("agent-sm", 9) }}
115 </span>
116 {% else %}
117 <span class="blm-commit-prov blm-commit-prov--human" title="{{ c.author }}">
118 {{ icon("user-sm", 9) }}
119 </span>
120 {% endif %}
121 <span class="blm-commit-count">{{ c.note_count }} sym{{ 's' if c.note_count != 1 else '' }}</span>
122 </div>
123 <div class="blm-commit-msg">{{ c.message | truncate(44, True, "…") }}</div>
124 <div class="blm-commit-meta">
125 {{ c.author }}
126 {% if c.is_agent and c.model_id %}
127 <span class="blm-commit-model">{{ c.model_id | replace("claude-", "") }}</span>
128 {% endif %}
129 &middot; {{ c.timestamp | fmtdate }}
130 </div>
131 </div>
132 </a>
133 {% endfor %}
134 </aside>
135
136 {# ── Right: blame content ─────────────────────────────────────────────── #}
137 <div class="blm-content">
138
139 {# ════════════════════════════════════════════════════════════════════ #}
140 {# SYMBOL BLAME ──────────────────────────────────────────────────────── #}
141 {# ════════════════════════════════════════════════════════════════════ #}
142 {% if blame_type == "symbol" %}
143 <div class="blm-symbol-list">
144 {% for entry in blame_entries %}
145 {% set c = commit_map.get(entry.commit_id, {}) %}
146 <details class="blm-card" style="--card-color: {{ commit_color.get(entry.commit_id, '#444') }}">
147 <summary class="blm-card-summary">
148
149 <div class="blm-card-main">
150 {# Top row: symbol name + op + signals #}
151 <div class="blm-card-top">
152 {{ icon("chevron-down", 10, "blm-expand-chevron") }}
153 <a class="blm-symbol-name blm-symbol-link"
154 href="{{ base_url }}/symbols?q={{ entry.symbol_name | urlencode }}"
155 title="{{ entry.symbol_address }}">{{ entry.symbol_name | e }}</a>
156
157 <span class="blm-op blm-op--{{ entry.op }}">{{ entry.op }}</span>
158
159 {% if entry.is_hotspot %}
160 <span class="blm-signal blm-signal--hotspot">{{ icon("flame", 10) }} hotspot</span>
161 {% endif %}
162 {% if entry.is_dead %}
163 <span class="blm-signal blm-signal--dead">🧊 dead</span>
164 {% endif %}
165 {% if entry.is_blast_risk %}
166 <span class="blm-signal blm-signal--blast" title="co-changes with {{ entry.blast_co_symbols[:2] | join(', ') }}">💥 blast</span>
167 {% endif %}
168 </div>
169
170 {# Bottom row: heat + author + commit sha #}
171 <div class="blm-card-bottom">
172 <div class="blm-heat" title="{{ entry.change_count }} change{{ 's' if entry.change_count != 1 else '' }}">
173 <span class="blm-heat-bar">
174 <span class="blm-heat-fill" style="width:{{ [entry.change_count / heat_max * 100, 2] | max | round | int }}%"></span>
175 </span>
176 <span class="blm-heat-count">{{ entry.change_count }}&times;</span>
177 </div>
178
179 <div class="blm-card-author">
180 {% if c.is_agent %}
181 <span class="blm-author-icon blm-author-icon--agent" title="{{ c.model_id or c.agent_id or 'AI agent' }}">
182 {{ icon("agent-sm", 9) }}
183 </span>
184 {% else %}
185 <span class="blm-author-icon blm-author-icon--human" title="{{ entry.author }}">
186 {{ icon("user-sm", 9) }}
187 </span>
188 {% endif %}
189 <span>{{ entry.author | e }}</span>
190 <span class="blm-card-dot">&middot;</span>
191 <span class="blm-card-time">{{ entry.timestamp | fmtdate }}</span>
192 </div>
193
194 <a class="blm-card-commit" href="{{ base_url }}/commits/{{ entry.commit_id }}">
195 {{ entry.commit_id[:8] }}
196 </a>
197 </div>
198 </div>
199
200 </summary>
201
202 {# Expanded: full symbol history #}
203 <div class="blm-history-panel">
204 {% set history = symbol_history_map.get(entry.symbol_address, []) %}
205 {% if history %}
206 <table class="blm-history-table">
207 <thead>
208 <tr>
209 <th>#</th>
210 <th>Commit</th>
211 <th>Op</th>
212 <th>Message</th>
213 <th>Author</th>
214 <th>When</th>
215 </tr>
216 </thead>
217 <tbody>
218 {% for h in history %}
219 {% set hc = commit_map.get(h.commit_id, {}) %}
220 <tr>
221 <td class="blm-hist-num">{{ loop.index }}</td>
222 <td class="blm-hist-sha">
223 <a href="{{ base_url }}/commits/{{ h.commit_id }}">{{ h.commit_id | short_id }}</a>
224 </td>
225 <td>
226 <span class="blm-op blm-op--{{ h.op }}">{{ h.op }}</span>
227 </td>
228 <td class="blm-hist-msg">{{ (hc.message or "") | truncate(60, True, "…") | e }}</td>
229 <td class="blm-hist-author">
230 {% if hc.is_agent %}
231 <span class="blm-author-icon blm-author-icon--agent" title="{{ hc.model_id or 'AI agent' }}">
232 {{ icon("agent-sm", 9) }}
233 </span>
234 {% else %}
235 <span class="blm-author-icon blm-author-icon--human">
236 {{ icon("user-sm", 9) }}
237 </span>
238 {% endif %}
239 {{ hc.author or (h.commit_id | short_id) | e }}
240 </td>
241 <td class="blm-hist-age">{{ (h.committed_at or "")[:10] }}</td>
242 </tr>
243 {% endfor %}
244 </tbody>
245 </table>
246 {% else %}
247 <p class="blm-history-empty">No detailed history available for this symbol.</p>
248 {% endif %}
249 <div class="blm-history-footer">
250 <a href="{{ base_url }}/symbols?q={{ entry.symbol_name | urlencode }}">View symbol detail &#8599;</a>
251 </div>
252 </div>
253
254 </details>
255 {% endfor %}
256 </div>
257
258 {# ════════════════════════════════════════════════════════════════════ #}
259 {# FILE BLAME ────────────────────────────────────────────────────────── #}
260 {# ════════════════════════════════════════════════════════════════════ #}
261 {% elif blame_type == "file" %}
262 {% set entry = blame_entries[0] %}
263 <div class="blm-file-view">
264
265 {# Commit info bar #}
266 <div class="blm-file-commit-bar">
267 <span class="blm-commit-dot" style="background: {{ commit_color.get(entry.commit_id, '#444') }}"></span>
268 <a class="blm-file-commit-sha" href="{{ base_url }}/commits/{{ entry.commit_id }}">
269 {{ entry.commit_id[:8] }}
270 </a>
271 <span class="blm-file-commit-msg">{{ entry.commit_message | truncate(72, True, "…") | e }}</span>
272 <span class="blm-file-commit-sep">&middot;</span>
273 <span class="blm-file-commit-author">{{ entry.author | e }}</span>
274 <span class="blm-file-commit-sep">&middot;</span>
275 <span class="blm-file-commit-time">{{ entry.timestamp | fmtdate }}</span>
276 </div>
277
278 {# Code lines with blame gutter #}
279 {% if file_lines %}
280 <div style="overflow-x:auto">
281 <table class="blm-code-table">
282 <tbody>
283 {% for line in file_lines %}
284 <tr class="blm-code-row" id="L{{ loop.index }}">
285 <td class="blm-gutter" style="border-left:3px solid {{ commit_color.get(entry.commit_id, '#444') }}">
286 <a class="blm-lnlink" href="#L{{ loop.index }}">{{ loop.index }}</a>
287 </td>
288 <td class="blm-code-cell">{{ line | e }}</td>
289 </tr>
290 {% endfor %}
291 </tbody>
292 </table>
293 </div>
294 {% if file_truncated %}
295 <div class="blm-code-truncated">
296 File truncated at 200 KB — <a href="{{ base_url }}/blob/{{ ref }}/{{ path }}">view full file &#8599;</a>
297 </div>
298 {% endif %}
299 {% else %}
300 <div class="blm-file-empty">
301 File content not available. <a href="{{ base_url }}/blob/{{ ref }}/{{ path }}">View in blob viewer &#8599;</a>
302 </div>
303 {% endif %}
304
305 </div>
306 {% endif %}
307
308 </div>{# .blm-content #}
309 </div>{# .blm-layout #}
310
311 {% endif %}{# blame_entries #}
312
313 {% endblock %}
314
315 {% block page_json %}{"page":"blame","baseUrl":{{ base_url | tojson }},"blameType":{{ blame_type | tojson }},"heatMax":{{ heat_max | tojson }}}{% endblock %}
File History 1 commit
sha256:7281683f5c41e5d88b6d8811fbdafebd3e01a0c9dcd90975cfcb444ba71e8e81 docs: add local source-of-truth for musehub#225, #226, #227… Sonnet 5 1 day ago