8fa36b774e
Key changes: - New: data_loader.py SQLite persistence with drop_sqlite_table - New: db_utils.py retry_on_lock decorator (3 retries, exponential backoff) - New: tool_registry.py with 27 MCP tools (filter_and_cluster, compute_scores, etc.) - New: tls_ref.py for TLS cipher/reference data - New: import_tlsdb.py management command - New: scripts/start_server.py for portable runtime - New: migrations 0003-0007 for SQLite table, display_id, llm fields - Changed: views.py unified pipeline worker, retry_run, display_id everywhere - Changed: models.py with display_id auto-assignment, run_type, sqlite_table, llm_thinking, tool_calls_json - Changed: urls.py added retry_run route - Changed: session_store.py robust JSON persistence - Changed: AGENTS.md v7 fix summary added - Changed: templates — globe rewrite (inertia/polar flip), auto.html (thinking/tool accordions), base.html (toast/config), all pages use display_id - Changed: run.bat PYTHONUTF8=1 - Deleted: entity_detector.py, entity_aggregator.py (replaced by filter_and_cluster clustering pipeline) - Test: 92/92 unit tests passing
56 lines
2.1 KiB
HTML
56 lines
2.1 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}Run #{{ run.display_id }} - TLS Analyzer{% endblock %}
|
|
{% block content %}
|
|
<div class="card">
|
|
<h2>Run #{{ run.display_id }} — {{ run.created_at|date:"Y-m-d H:i" }}</h2>
|
|
<p>Status: <span class="badge {% if run.status == 'completed' %}badge-success{% elif run.status == 'failed' %}badge-danger{% else %}badge-info{% endif %}">{{ run.get_status_display }}</span></p>
|
|
<p>CSV: <code>{{ run.csv_glob }}</code></p>
|
|
</div>
|
|
|
|
<div class="grid-3">
|
|
<div class="card" style="text-align:center;">
|
|
<div class="stat">{{ run.total_flows|default:"0" }}</div>
|
|
<div class="stat-label">Total Flows</div>
|
|
</div>
|
|
<div class="card" style="text-align:center;">
|
|
<div class="stat">{{ run.entity_count|default:"0" }}</div>
|
|
<div class="stat-label">Entities</div>
|
|
</div>
|
|
<div class="card" style="text-align:center;">
|
|
<div class="stat">{{ run.cluster_count|default:"0" }}</div>
|
|
<div class="stat-label">Clusters</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Clusters</h2>
|
|
<a href="{% url 'analysis:cluster_overview' run.display_id %}" class="btn btn-primary" style="margin-bottom:1rem;">View Cluster Overview</a>
|
|
{% if clusters %}
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Cluster</th>
|
|
<th>Size</th>
|
|
<th>Proportion</th>
|
|
<th>Silhouette</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for c in clusters %}
|
|
<tr>
|
|
<td><span class="badge badge-info">#{{ c.cluster_label }}</span></td>
|
|
<td>{{ c.size }}</td>
|
|
<td>{{ c.proportion|floatformat:2 }}</td>
|
|
<td>{{ c.silhouette_score|floatformat:4|default:"-" }}</td>
|
|
<td><a href="{% url 'analysis:cluster_detail' run.display_id c.cluster_label %}" class="btn btn-primary">Detail</a></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<div class="empty-state"><p>No clusters yet.</p></div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|