diff --git a/arborist_viz/routes.py b/arborist_viz/routes.py index 10c1a32..4a99ee0 100644 --- a/arborist_viz/routes.py +++ b/arborist_viz/routes.py @@ -59,9 +59,14 @@ def includeme(config): config.add_route("sessions_list", "/sessions") config.add_route("sessions_find", "/sessions/find") config.add_route("sessions_tree", "/sessions/{sid}") + config.add_route("cache_key_page", "/cache/{cache_key}") config.add_route("api_sessions_list", "/api/sessions") config.add_route("api_sessions_find", "/api/sessions/find") config.add_route("api_sessions_tree", "/api/sessions/{sid}") + # Sessions-shard view of a providence cache_key (every session node + # referencing it). Distinct from /api/cache/ which targets the + # providence_cache row itself (ticket #000069 §13 §6.7). + config.add_route("api_session_cache_key", "/api/cache-key/{cache_key}") # SSE — §3-corrected replaces WS routes with text/event-stream. config.add_route("sse_audit_live", "/sse/audit/live") diff --git a/arborist_viz/static/css/viz.css b/arborist_viz/static/css/viz.css index 9a96e25..a83048a 100644 --- a/arborist_viz/static/css/viz.css +++ b/arborist_viz/static/css/viz.css @@ -673,3 +673,70 @@ code, pre { font-family: var(--mono); font-size: 12px; } .cmd-cite { font-size: 0.75em; opacity: 0.7; padding: 0.05em 0.4em; border-radius: 0.2em; background: rgba(255,255,255,0.06); } + +/* ---- node cards + answer + metadata (richer tree views) -------------- */ + +.cmd-panel-wide { max-width: none; padding: 1.5em 2em; } + +.cmd-hash-block { word-break: break-all; font-size: 0.85em; opacity: 0.85; } + +.cmd-node-card { + background: rgba(255,255,255,0.03); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 0.3em; + padding: 0.8em 1em; + margin: 0.4em 0; +} +.cmd-node-card-head { + display: flex; gap: 0.6em; align-items: baseline; flex-wrap: wrap; + margin-bottom: 0.4em; +} +.cmd-node-q { + font-size: 1.05em; font-weight: 500; + margin: 0.3em 0 0.5em 0; +} +.cmd-current-pill, .cmd-branch-pill { + font-size: 0.7em; padding: 0.05em 0.5em; + border-radius: 0.2em; font-weight: 600; + text-transform: uppercase; letter-spacing: 0.05em; +} +.cmd-current-pill { background: rgba(120, 200, 255, 0.25); color: #8af; } +.cmd-branch-pill { background: rgba(220, 180, 80, 0.25); color: #db8; } + +.cmd-node-answer summary, +.cmd-node-meta summary { + cursor: pointer; opacity: 0.7; font-size: 0.85em; + padding: 0.3em 0; user-select: none; +} +.cmd-node-answer[open] summary, +.cmd-node-meta[open] summary { opacity: 1; } +.cmd-answer-pre { + background: rgba(0,0,0,0.25); + padding: 0.8em 1em; + border-left: 2px solid rgba(120, 200, 255, 0.4); + border-radius: 0.2em; + font-size: 0.85em; + line-height: 1.5; + white-space: pre-wrap; + word-break: break-word; + overflow-x: auto; + max-height: 600px; + overflow-y: auto; +} + +.cmd-meta-dl { + display: grid; + grid-template-columns: max-content 1fr; + gap: 0.2em 1em; + font-size: 0.85em; + padding: 0.5em 0; +} +.cmd-meta-dl dt { opacity: 0.65; } +.cmd-meta-dl dd { margin: 0; word-break: break-all; } +.cmd-meta-dl code { font-size: 0.95em; } + +.cmd-tree-current > .cmd-node-card { border-color: rgba(120, 200, 255, 0.5); } +.cmd-tree-branch > .cmd-node-card { border-color: rgba(220, 180, 80, 0.5); } + +/* Override the tree-line styles (old layout) — cards replace them. */ +.cmd-tree-current > .cmd-tree-line::after { content: none; } diff --git a/arborist_viz/templates/cache_key.jinja2 b/arborist_viz/templates/cache_key.jinja2 new file mode 100644 index 0000000..a555117 --- /dev/null +++ b/arborist_viz/templates/cache_key.jinja2 @@ -0,0 +1,52 @@ +{% extends "base.jinja2" %} +{% block body %} +
+
+

cache_key

+

{{ cache_key }}

+

+ {{ hits|length }} session node(s) reference this providence cache entry — + a cache hit reused across {{ hits|map(attribute='sid')|unique|list|length }} session(s). +

+

← all sessions · JSON

+
+ + {% if hits %} + {% set first = hits[0] %} +
+
+ {{ first.audit_mode }} + {{ first.question }} +
+ {% if first.cited_titles %} +
+ {% for t in first.cited_titles %}{{ t }}{% endfor %} +
+ {% endif %} +
+ answer +
{{ first.answer_text }}
+
+
+ +

Referenced by

+ + + + + + {% for n in hits %} + + + + + + + {% endfor %} + +
batessessionauditcreated
{{ n.bates }}{{ n.sid }}{{ n.audit_mode }}{{ n.created_at }}
+ {% else %} +

no session nodes reference this cache_key

+ {% endif %} +
+{% endblock %} diff --git a/arborist_viz/templates/sessions_tree.jinja2 b/arborist_viz/templates/sessions_tree.jinja2 index 110fb65..726014c 100644 --- a/arborist_viz/templates/sessions_tree.jinja2 +++ b/arborist_viz/templates/sessions_tree.jinja2 @@ -2,18 +2,50 @@ {% macro render_node(node, kids_of, branch_set, current_bates, this_sid, depth=0) -%}
  • -
    - {{ node.bates }} - {{ node.audit_mode }} - {% if node.sid != this_sid %}[from {{ node.sid }}]{% endif %} - {% if node.label %}{{ '{' + node.label + '}' }}{% endif %} - {{ (node.question or '')[:120] }} -
    - {% if node.cited_titles %} -
    - {% for t in node.cited_titles %}{{ t }}{% endfor %} -
    - {% endif %} +
    +
    + {{ node.bates }} + {{ node.audit_mode }} + {% if node.sid != this_sid %}[from {{ node.sid }}]{% endif %} + {% if node.label %}{{ '{' + node.label + '}' }}{% endif %} + {% if node.bates == current_bates %}current{% endif %} + {% if node.bates in branch_set %}branch{% endif %} +
    + +
    {{ node.question }}
    + + {% if node.cited_titles %} +
    + {% for t in node.cited_titles %}{{ t }}{% endfor %} +
    + {% endif %} + + {% if node.answer_text %} +
    + answer ({{ node.answer_text|length }} chars) +
    {{ node.answer_text }}
    +
    + {% endif %} + +
    + hashes / metadata +
    +
    cache_key
    +
    {% if node.cache_key %}{{ node.cache_key }}{% else %}(none — canonical_projection){% endif %}
    +
    node_hash
    +
    {{ node.node_hash }}
    +
    subtree_hash
    +
    {{ node.subtree_hash }}
    +
    created
    +
    {{ node.created_at }}
    + {% if node.parent_bates %} +
    parent
    +
    {{ node.parent_bates }}
    + {% endif %} +
    +
    +
    + {% set kids = kids_of.get(node.bates, []) %} {% if kids %}